# HG changeset patch # User bsw # Date 1404947988 -7200 # Node ID 701a5cf6b067008e2097568556c91c77ae6a2763 # Parent a6c7bf07badb1d31d2c581a3bdbec7353ddda9c0 Imported LiquidFeedback Frontend 3.0 branch diff -r a6c7bf07badb -r 701a5cf6b067 INSTALL.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/INSTALL.html Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,191 @@ + + + LiquidFeedback Installation Instructions + + + +

LiquidFeedback Installation Instructions

+

This document gives a short outline about the necessary steps to setup a LiquidFeedback system.

+

1. Install necessary dependencies

+

If you're using a Debian system, make sure that the following packages are installed:

+ +

If you're using any other Linux distribution or BSD system, install the necessary software components accordingly.

+

2. Ensure that the user account of your webserver has access to the database

+

Whichever useraccount is used by the webserver (usually www-data) needs to have access to your PostgreSQL installation. This is done by executing PostgreSQL's shell command createuser as database superuser (usually pgsql, or postgres for Debian installations):

+
su - postgres
+createuser
+
+Enter name of role to add: www-data
+Shall the new role be a superuser? (y/n) n
+Shall the new role be allowed to create databases? (y/n) y
+Shall the new role be allowed to create more new roles? (y/n) n
+
+exit
+

3. Install and configure LiquidFeedback-Core

+

We recommend to create the database with the same user as your webserver (usually www-data) to avoid having to setup database privileges.

+

The example below installs the database as www-data and stores the two executables lf_update and lf_update_issue_order in the directory /opt/liquid_feedback_core/:

+
# Download and unpack LiquidFeedback-Core
+# from http://www.public-software-group.org/pub/projects/liquid_feedback/backend/
+make
+mkdir /opt/liquid_feedback_core
+cp core.sql lf_update lf_update_issue_order /opt/liquid_feedback_core
+su - www-data
+cd /opt/liquid_feedback_core
+createdb liquid_feedback
+createlang plpgsql liquid_feedback  # command may be omitted, depending on PostgreSQL version
+psql -v ON_ERROR_STOP=1 -f core.sql liquid_feedback
+

A simple configuration may look as follows:

+
psql liquid_feedback
+
+INSERT INTO system_setting (member_ttl) VALUES ('1 year');
+INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (false, '1 hour', 20, 6);
+INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (false, '1 day', 80, 12);
+INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (true, '1 hour', 200, 60);
+INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (true, '1 day', 800, 120);
+INSERT INTO policy (index, name, admission_time, discussion_time, verification_time, voting_time, issue_quorum_num, issue_quorum_den, initiative_quorum_num, initiative_quorum_den) VALUES (1, 'Default policy', '8 days', '15 days', '8 days', '15 days', 10, 100, 10, 100);
+INSERT INTO unit (name) VALUES ('Our organization');
+INSERT INTO area (unit_id, name) VALUES (1, 'Default area');
+INSERT INTO allowed_policy (area_id, policy_id, default_policy) VALUES (1, 1, TRUE);
+

If you want to create an admin user with an empty password (CAUTION!), then execute the following SQL statement:

+
INSERT INTO member (login, name, admin, password) VALUES ('admin', 'Administrator', TRUE, '$1$/EMPTY/$NEWt7XJg2efKwPm4vectc1');
+

Exit the psql interface by typing:

+
\q
+

And don't forget to quit the www-data shell:

+
exit
+

4. Install WebMCP

+

Note: Using Debian, it may be necessary to append -I /usr/include/lua5.1 at the end of the CFLAGS line in Makefile.options of the WebMCP source distibution:

+
# Download and unpack WebMCP
+# from http://www.public-software-group.org/pub/projects/webmcp/
+vi Makefile.options  # Debian requires  -I /usr/include/lua5.1  at end of CFLAGS line
+make
+mkdir /opt/webmcp
+cp -RL framework/* /opt/webmcp/
+

5. Install RocketWiki LqFb-Edition

+
# Download and unpack "RocketWiki LqFb-Edition"
+# from http://www.public-software-group.org/pub/projects/rocketwiki/liquid_feedback_edition/
+make
+mkdir /opt/rocketwiki-lqfb
+cp rocketwiki-lqfb rocketwiki-lqfb-compat /opt/rocketwiki-lqfb/
+

If you experience problems with multi-byte encoding (UTF-8) later, then apply the following patch to both rocketwiki-lqfb.hs and rocketwiki-lqfb-compat.hs prior compilation:

+
--- rocketwiki-lqfb.hs
++++ rocketwiki-lqfb.hs
+@@ -1,4 +1,6 @@
+
++import System.IO (hSetEncoding, stdin, stdout, utf8)
++
+ import Text.ParserCombinators.Parsec
+ import Control.Applicative ((<$>), (<*>))
+ import Data.List (intercalate)
+@@ -405,7 +407,10 @@
+       return htmlEntity
+ 
+ 
+-main = interact wikiParse
++main = do
++  hSetEncoding stdin utf8
++  hSetEncoding stdout utf8
++  interact wikiParse
+
+ wikiParse str
+   | success parseResult = html
+

6. Install the LiquidFeedback-Frontend

+

Unpack source tree into appropriate directory, e.g. /opt/liquid_feedback_frontend:

+
# Download LiquidFeedback-Frontend
+# from http://www.public-software-group.org/pub/projects/liquid_feedback/frontend/
+mv liquid_feedback_frontend-vX.X.X /opt/liquid_feedback_frontend
+

Create HTML code for help texts:

+
cd /opt/liquid_feedback_frontend/locale
+PATH=/opt/rocketwiki-lqfb:$PATH make
+

Make tmp/ directory of LiquidFeedback-Frontend writable for webserver:

+
chown www-data /opt/liquid_feedback_frontend/tmp
+

Compile binary for fast delivery of member images:

+
cd /opt/liquid_feedback_frontend/fastpath
+vi getpic.c  # check and modify #define commands as necessary
+make
+

7. Configure mail system

+

It may be necessary to configure your server's mail system, e.g. running dpkg-reconfigure exim4-config on a Debian system.

+

8. Configure the Webserver for LiquidFeedback:

+

A sample configuration for lighttpd is given below (assuming mod_alias has been included elsewhere):

+
server.modules += ("mod_cgi", "mod_rewrite", "mod_redirect", "mod_setenv")
+
+# Enable CGI-Execution of *.lua files through lua binary
+cgi.assign += ( ".lua" => "/usr/bin/lua5.1" )
+
+alias.url += ( "/lf/fastpath/" => "/opt/liquid_feedback_frontend/fastpath/",
+               "/lf/static"    => "/opt/liquid_feedback_frontend/static",
+               "/lf"           => "/opt/webmcp/cgi-bin" )
+
+# Configure environment for demo application
+$HTTP["url"] =~ "^/lf" {
+  setenv.add-environment += (
+    "LANG" => "en_US.UTF-8",
+    "WEBMCP_APP_BASEPATH" => "/opt/liquid_feedback_frontend/",
+    "WEBMCP_CONFIG_NAME"  => "myconfig")
+}
+
+# URL beautification
+url.rewrite-once += (
+  # do not rewrite static URLs
+      "^/lf/fastpath/(.*)$" => "/lf/fastpath/$1",
+      "^/lf/static/(.*)$"   => "/lf/static/$1",
+
+  # dynamic URLs
+      "^/lf/([^\?]*)(\?(.*))?$" => "/lf/webmcp-wrapper.lua?_webmcp_path=$1&$3",
+
+)
+
+$HTTP["url"] =~ "^/lf/fastpath/" {
+  cgi.assign = ( "" => "" )
+  setenv.add-response-header = ( "Cache-Control" => "private; max-age=86400" )
+}
+

If you're using Debian, you may want to create a file with the name /etc/lighttpd/conf-available/60-liquidfeedback.conf and create a softlink in /etc/lighttpd/conf-enabled/.

+

9. Configure the LiquidFeedback-Frontend:

+
cd /opt/liquid_feedback_frontend/config
+cp example.lua myconfig.lua
+# edit myconfig.lua according to your needs
+

Use the following option in your configuration file to enable fast image loading:

+
config.fastpath_url_func = function(member_id, image_type)
+  return request.get_absolute_baseurl() .. "fastpath/getpic?" .. tostring(member_id) .. "+" .. tostring(image_type)
+end
+

10. Setup regular execution of lf_update and lf_update_suggestion_order

+

The executables lf_update and lf_update_suggestion_order must be executed regularly. This may be achieved by creating a file named /opt/liquid_feedback_core/lf_updated with the following contents:

+
#!/bin/sh
+
+PIDFILE="/var/run/lf_updated.pid"
+PID=$$
+
+if [ -f "${PIDFILE}" ] && kill -CONT $( cat "${PIDFILE}" ); then
+  echo "lf_updated is already running."
+  exit 1
+fi
+
+echo "${PID}" > "${PIDFILE}"
+
+while true; do
+  su - www-data -c 'nice /opt/liquid_feedback_core/lf_update dbname=liquid_feedback 2>&1 | logger -t "lf_updated"'
+  su - www-data -c 'nice /opt/liquid_feedback_core/lf_update_suggestion_order dbname=liquid_feedback 2>&1 | logger -t "lf_updated"'
+  sleep 5
+done
+

This file must be marked as executable:

+
chmod +x /opt/liquid_feedback_core/lf_updated
+

And this file should be started automatically at system boot.

+

11. Setup notification loop in background

+

In addition to regular execution of lf_update and lf_update_suggestion_order, the following commands should be executed in background:

+
su - www-data
+cd /opt/liquid_feedback_frontend/
+echo "Event:send_notifications_loop()" | ../webmcp/bin/webmcp_shell myconfig
+

12. Start the sytem

+

After lf_update has been executed at least once, and the webserver has been restarted (using the configuration above), you should be able to access your LiquidFeedback system.

+ + diff -r a6c7bf07badb -r 701a5cf6b067 INSTALL.mkd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/INSTALL.mkd Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,289 @@ +LiquidFeedback Installation Instructions +======================================== + +This document gives a short outline about the necessary steps to setup a +LiquidFeedback system. + + +1. Install necessary dependencies +--------------------------------- + +If you're using a Debian system, make sure that the following packages are +installed: + + * lua5.1 + * postgresql + * build-essential + * libpq-dev + * liblua5.1-0-dev + * lighttpd + * ghc + * libghc6-parsec3-dev + * imagemagick + * exim4 + +If you're using any other Linux distribution or BSD system, install the +necessary software components accordingly. + + +2. Ensure that the user account of your webserver has access to the database +---------------------------------------------------------------------------- + +Whichever useraccount is used by the webserver (usually `www-data`) needs to +have access to your PostgreSQL installation. This is done by executing +PostgreSQL's shell command `createuser` as database superuser (usually `pgsql`, +or `postgres` for Debian installations): + + su - postgres + createuser + + Enter name of role to add: www-data + Shall the new role be a superuser? (y/n) n + Shall the new role be allowed to create databases? (y/n) y + Shall the new role be allowed to create more new roles? (y/n) n + + exit + + +3. Install and configure LiquidFeedback-Core +-------------------------------------------- + +We recommend to create the database with the same user as your webserver +(usually `www-data`) to avoid having to setup database privileges. + +The example below installs the database as `www-data` and stores the two +executables `lf_update` and `lf_update_issue_order` in the directory +`/opt/liquid_feedback_core/`: + + # Download and unpack LiquidFeedback-Core + # from http://www.public-software-group.org/pub/projects/liquid_feedback/backend/ + make + mkdir /opt/liquid_feedback_core + cp core.sql lf_update lf_update_issue_order /opt/liquid_feedback_core + su - www-data + cd /opt/liquid_feedback_core + createdb liquid_feedback + createlang plpgsql liquid_feedback # command may be omitted, depending on PostgreSQL version + psql -v ON_ERROR_STOP=1 -f core.sql liquid_feedback + +A simple configuration may look as follows: + + psql liquid_feedback + + INSERT INTO system_setting (member_ttl) VALUES ('1 year'); + INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (false, '1 hour', 20, 6); + INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (false, '1 day', 80, 12); + INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (true, '1 hour', 200, 60); + INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (true, '1 day', 800, 120); + INSERT INTO policy (index, name, admission_time, discussion_time, verification_time, voting_time, issue_quorum_num, issue_quorum_den, initiative_quorum_num, initiative_quorum_den) VALUES (1, 'Default policy', '8 days', '15 days', '8 days', '15 days', 10, 100, 10, 100); + INSERT INTO unit (name) VALUES ('Our organization'); + INSERT INTO area (unit_id, name) VALUES (1, 'Default area'); + INSERT INTO allowed_policy (area_id, policy_id, default_policy) VALUES (1, 1, TRUE); + +If you want to create an admin user with an empty password (CAUTION!), then execute the following SQL statement: + + INSERT INTO member (login, name, admin, password) VALUES ('admin', 'Administrator', TRUE, '$1$/EMPTY/$NEWt7XJg2efKwPm4vectc1'); + +Exit the `psql` interface by typing: + + \q + +And don't forget to quit the `www-data` shell: + + exit + + +4. Install WebMCP +----------------- + +Note: Using Debian, it may be necessary to append `-I /usr/include/lua5.1` at +the end of the CFLAGS line in `Makefile.options` of the WebMCP source +distibution: + + # Download and unpack WebMCP + # from http://www.public-software-group.org/pub/projects/webmcp/ + vi Makefile.options # Debian requires -I /usr/include/lua5.1 at end of CFLAGS line + make + mkdir /opt/webmcp + cp -RL framework/* /opt/webmcp/ + + +5. Install RocketWiki LqFb-Edition +---------------------------------- + + # Download and unpack "RocketWiki LqFb-Edition" + # from http://www.public-software-group.org/pub/projects/rocketwiki/liquid_feedback_edition/ + make + mkdir /opt/rocketwiki-lqfb + cp rocketwiki-lqfb rocketwiki-lqfb-compat /opt/rocketwiki-lqfb/ + +If you experience problems with multi-byte encoding (UTF-8) later, then apply +the following patch to both `rocketwiki-lqfb.hs` and +`rocketwiki-lqfb-compat.hs` prior compilation: + + --- rocketwiki-lqfb.hs + +++ rocketwiki-lqfb.hs + @@ -1,4 +1,6 @@ + + +import System.IO (hSetEncoding, stdin, stdout, utf8) + + + import Text.ParserCombinators.Parsec + import Control.Applicative ((<$>), (<*>)) + import Data.List (intercalate) + @@ -405,7 +407,10 @@ + return htmlEntity + + + -main = interact wikiParse + +main = do + + hSetEncoding stdin utf8 + + hSetEncoding stdout utf8 + + interact wikiParse + + wikiParse str + | success parseResult = html + + +6. Install the LiquidFeedback-Frontend +-------------------------------------- + +Unpack source tree into appropriate directory, e.g. `/opt/liquid_feedback_frontend`: + + # Download LiquidFeedback-Frontend + # from http://www.public-software-group.org/pub/projects/liquid_feedback/frontend/ + mv liquid_feedback_frontend-vX.X.X /opt/liquid_feedback_frontend + +Create HTML code for help texts: + + cd /opt/liquid_feedback_frontend/locale + PATH=/opt/rocketwiki-lqfb:$PATH make + +Make `tmp/` directory of LiquidFeedback-Frontend writable for webserver: + + chown www-data /opt/liquid_feedback_frontend/tmp + +Compile binary for fast delivery of member images: + + cd /opt/liquid_feedback_frontend/fastpath + vi getpic.c # check and modify #define commands as necessary + make + + +7. Configure mail system +------------------------ + +It may be necessary to configure your server's mail system, e.g. running +`dpkg-reconfigure exim4-config` on a Debian system. + + +8. Configure the Webserver for LiquidFeedback: +---------------------------------------------- + +A sample configuration for `lighttpd` is given below (assuming `mod_alias` has +been included elsewhere): + + server.modules += ("mod_cgi", "mod_rewrite", "mod_redirect", "mod_setenv") + + # Enable CGI-Execution of *.lua files through lua binary + cgi.assign += ( ".lua" => "/usr/bin/lua5.1" ) + + alias.url += ( "/lf/fastpath/" => "/opt/liquid_feedback_frontend/fastpath/", + "/lf/static" => "/opt/liquid_feedback_frontend/static", + "/lf" => "/opt/webmcp/cgi-bin" ) + + # Configure environment for demo application + $HTTP["url"] =~ "^/lf" { + setenv.add-environment += ( + "LANG" => "en_US.UTF-8", + "WEBMCP_APP_BASEPATH" => "/opt/liquid_feedback_frontend/", + "WEBMCP_CONFIG_NAME" => "myconfig") + } + + # URL beautification + url.rewrite-once += ( + # do not rewrite static URLs + "^/lf/fastpath/(.*)$" => "/lf/fastpath/$1", + "^/lf/static/(.*)$" => "/lf/static/$1", + + # dynamic URLs + "^/lf/([^\?]*)(\?(.*))?$" => "/lf/webmcp-wrapper.lua?_webmcp_path=$1&$3", + + ) + + $HTTP["url"] =~ "^/lf/fastpath/" { + cgi.assign = ( "" => "" ) + setenv.add-response-header = ( "Cache-Control" => "private; max-age=86400" ) + } + +If you're using Debian, you may want to create a file with the name +`/etc/lighttpd/conf-available/60-liquidfeedback.conf` and create a softlink in +`/etc/lighttpd/conf-enabled/`. + + +9. Configure the LiquidFeedback-Frontend: +----------------------------------------- + + cd /opt/liquid_feedback_frontend/config + cp example.lua myconfig.lua + # edit myconfig.lua according to your needs + +Use the following option in your configuration file to enable fast image +loading: + + config.fastpath_url_func = function(member_id, image_type) + return request.get_absolute_baseurl() .. "fastpath/getpic?" .. tostring(member_id) .. "+" .. tostring(image_type) + end + + +10. Setup regular execution of `lf_update` and `lf_update_suggestion_order` +--------------------------------------------------------------------------- + +The executables `lf_update` and `lf_update_suggestion_order` must be executed +regularly. This may be achieved by creating a file named +`/opt/liquid_feedback_core/lf_updated` with the following contents: + + #!/bin/sh + + PIDFILE="/var/run/lf_updated.pid" + PID=$$ + + if [ -f "${PIDFILE}" ] && kill -CONT $( cat "${PIDFILE}" ); then + echo "lf_updated is already running." + exit 1 + fi + + echo "${PID}" > "${PIDFILE}" + + while true; do + su - www-data -c 'nice /opt/liquid_feedback_core/lf_update dbname=liquid_feedback 2>&1 | logger -t "lf_updated"' + su - www-data -c 'nice /opt/liquid_feedback_core/lf_update_suggestion_order dbname=liquid_feedback 2>&1 | logger -t "lf_updated"' + sleep 5 + done + +This file must be marked as executable: + + chmod +x /opt/liquid_feedback_core/lf_updated + +And this file should be started automatically at system boot. + + +11. Setup notification loop in background +----------------------------------------- + +In addition to regular execution of `lf_update` and +`lf_update_suggestion_order`, the following commands should be executed in +background: + + su - www-data + cd /opt/liquid_feedback_frontend/ + echo "Event:send_notifications_loop()" | ../webmcp/bin/webmcp_shell myconfig + + +12. Start the sytem +------------------- + +After `lf_update` has been executed at least once, and the webserver has been +restarted (using the configuration above), you should be able to access your +LiquidFeedback system. + + diff -r a6c7bf07badb -r 701a5cf6b067 LICENSE --- a/LICENSE Thu Jul 10 01:02:43 2014 +0200 +++ b/LICENSE Thu Jul 10 01:19:48 2014 +0200 @@ -1,4 +1,4 @@ -Copyright (c) 2009-2013 Public Software Group e. V., Berlin, Germany +Copyright (c) 2009-2014 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"), diff -r a6c7bf07badb -r 701a5cf6b067 app/main/_filter/21_auth.lua --- a/app/main/_filter/21_auth.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/_filter/21_auth.lua Thu Jul 10 01:19:48 2014 +0200 @@ -5,8 +5,7 @@ local auth_needed = not ( module == 'index' and ( - view == "index" - or view == "login" +view == "login" or action == "login" or view == "register" or action == "register" @@ -26,16 +25,17 @@ if app.session:has_access("anonymous") then if - module == "area" and view == "show" + module == "index" and view == "index" + or module == "area" and view == "show" or module == "unit" and view == "show" or module == "policy" and view == "show" or module == "policy" and view == "list" or module == "issue" and view == "show" or module == "initiative" and view == "show" + or module == "initiative" and view == "history" or module == "suggestion" and view == "show" or module == "draft" and view == "diff" or module == "draft" and view == "show" - or module == "draft" and view == "list" or module == "index" and view == "search" or module == "index" and view == "usage_terms" then @@ -44,11 +44,16 @@ end +if app.session:has_access("authors_pseudonymous") then + if module == "member_image" and view == "show" then + auth_needed = false + end +end + if app.session:has_access("all_pseudonymous") then - if module == "member_image" and view == "show" - or module == "vote" and view == "show_incoming" + if module == "vote" and view == "show_incoming" + or module == "member" and view == "list" or module == "interest" and view == "show_incoming" - or module == "supporter" and view == "show_incoming" or module == "vote" and view == "list" then auth_needed = false end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/_filter_view/30_navigation.lua --- a/app/main/_filter_view/30_navigation.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/_filter_view/30_navigation.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,88 +1,86 @@ -slot.select('navigation', function() +slot.select ( 'instance_name', function () + slot.put ( encode.html ( config.instance_name ) ) +end) - ui.link{ - content = function() - ui.tag{ attr = { class = "logo_liquidfeedback" }, content = _"LiquidFeedback" } - slot.put(" · ") - ui.tag{ content = config.instance_name } - end, - module = 'index', - view = 'index' - } - if app.session:has_access("anonymous") and not (app.session.needs_delegation_check) then +slot.select ( 'navigation_right', function () - ui.link{ - content = _"Search", - module = 'index', - view = 'search' - } + if app.session:has_access ("anonymous") and not (app.session.needs_delegation_check) then - if app.session.member == nil then - ui.link{ - text = _"Login", - module = 'index', - view = 'login', - params = { - redirect_module = request.get_module(), - redirect_view = request.get_view(), - redirect_id = param.get_id() + ui.form { + attr = { class = "inline search" }, + method = "get", + module = "index", view = "search", + content = function () + + ui.field.text { + attr = { placeholder = "search" }, + name = "q" } - } - end + + end + } + + ui.link { + attr = { class = "searchLink" }, + module = "index", view = "search", content = function () + ui.image { static = "icons/16/magnifier.png" } + end + } end - + if app.session.member == nil then - ui.link{ + + slot.put ( " " ) + + ui.link { + text = _"Login", + module = 'index', + view = 'login', + params = { + redirect_module = request.get_module(), + redirect_view = request.get_view(), + redirect_id = param.get_id() + } + } + + slot.put ( " " ) + + ui.link { text = _"Registration", module = 'index', view = 'register' } + end + + + if app.session.member then + + slot.put ( " " ) + + ui.tag { attr = { id = "member_menu" }, content = function() + util.micro_avatar(app.session.member) + end } + + end -- if app.session.member + end) +-- show notifications about things the user should take care of +if app.session.member then + execute.view{ + module = "index", view = "_sidebar_notifications", params = { + mode = "link" + } + } +end -slot.select('navigation_right', function() - ui.tag{ - tag = "ul", - attr = { id = "member_menu" }, - content = function() - ui.tag{ - tag = "li", - content = function() - ui.link{ - module = "index", - view = "menu", - content = function() - if app.session.member_id then - execute.view{ - module = "member_image", - view = "_show", - params = { - member = app.session.member, - image_type = "avatar", - show_dummy = true, - class = "micro_avatar", - } - } - ui.tag{ content = app.session.member.name } - else - ui.tag{ content = _"Select language" } - end - end - } - execute.view{ module = "index", view = "_menu" } - end - } - end - } -end) - -slot.select("footer", function() +slot.select ("footer", function () if app.session.member_id and app.session.member.admin then - ui.link{ - text = _"Admin", + ui.link { + text = _"System settings", module = 'admin', view = 'index' } @@ -102,8 +100,6 @@ } end slot.put(" · ") - ui.tag{ content = _"This site is using" } - slot.put(" ") ui.link{ text = _"LiquidFeedback", external = "http://www.public-software-group.org/liquid_feedback" diff -r a6c7bf07badb -r 701a5cf6b067 app/main/_layout/default.html --- a/app/main/_layout/default.html Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/_layout/default.html Thu Jul 10 01:19:48 2014 +0200 @@ -1,67 +1,277 @@ - - - - <!-- WEBMCP SLOTNODIV html_title --> - - - - - - - - - - - - - -
-
- - -
- -
-
+ + + + <!-- WEBMCP SLOTNODIV html_title --> + + + + + + + + + + + + + + +
+
+ + + + + +
+
+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + + + + + +
+
+
+
+
+ +
+ + +
+ +
+ +
-
- -
- -
-
- -
-
- -
-
- -
-
-
- - +
+
+ +
+ +
+ - - +
+ + + + + + + diff -r a6c7bf07badb -r 701a5cf6b067 app/main/_layout/system_error.html --- a/app/main/_layout/system_error.html Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/_layout/system_error.html Thu Jul 10 01:19:48 2014 +0200 @@ -1,75 +1,86 @@ - - - LiquidFeedback Error - - - - - -
- - Ooops, a system error occured -
-

- Most probably you found a software bug. Don't panic, you can now choose one of the following options: -

- - Go to start page - Retry request - Create bug report - -
- -
- - Leider ist ein Systemfehler aufgetreten -
-

- Du hast vermutlich gerade einen Fehler in der Software entdeckt. Das ist kein Grund zur Panik, dir bleiben die folgenden Optionen: -

- - Weiter zur Startseite - Anfrage wiederholen - Fehlerbericht erstellen - -
-

- If you write a bug report, please include the following output in your bug report.
- Falls Du einen Fehlerbericht erstellst, füge bitte die folgenden Ausgaben mit ein. -

- - - -
- -
- -
close
+ + + + <!-- WEBMCP SLOTNODIV html_title --> + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
System error
+
+ +
+ + +
+
+
+
+

A system error occured

+
+
+ Sorry, a system error occured. +
+
+
+ Go back to home page +
+
+
+
+
+
+ +
+ +
+ +
+ +
+ + \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/_action/area_update.lua --- a/app/main/admin/_action/area_update.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/_action/area_update.lua Thu Jul 10 01:19:48 2014 +0200 @@ -2,6 +2,13 @@ param.update(area, "unit_id", "name", "description", "active") +if #area.name < 1 then + slot.select("error", function() + ui.tag{ content = _"Please choose an area name" } + end) + return false +end + area:save() param.update_relationship{ diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/area_show.lua --- a/app/main/admin/area_show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/area_show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,25 +1,27 @@ local id = param.get_id() +local hint = not id + local area = Area:by_id(id) or Area:new() if not area.unit_id then area.unit_id = param.get("unit_id", atom.integer) end -ui.title(_"Create / edit area") +ui.titleAdmin(_"area") ui.form{ - attr = { class = "vertical" }, + attr = { class = "vertical section" }, record = area, module = "admin", action = "area_update", routing = { - default = { + ok = { mode = "redirect", module = "admin", - view = "area_list", + view = "index", params = { unit_id = area.unit_id } - } + }, }, id = id, content = function() @@ -34,25 +36,38 @@ def_policy[#def_policy+1] = record end - ui.field.hidden{ name = "unit_id", value = area.unit_id } - ui.field.text{ label = _"Unit", value = area.unit.name, readonly = true } - ui.field.text{ label = _"Name", name = "name" } - ui.field.text{ label = _"Description", name = "description", multiline = true } - ui.field.select{ label = _"Default Policy", name = "default_policy", - value=area.default_policy and area.default_policy.id or "-1", - foreign_records = def_policy, - foreign_id = "id", - foreign_name = "name" - } - ui.multiselect{ label = _"Policies", name = "allowed_policies[]", - foreign_records = policies, - foreign_id = "id", - foreign_name = "name", - connecting_records = area.allowed_policies or {}, - foreign_reference = "id", - } - slot.put("

") - ui.field.boolean{ label = _"Active?", name = "active" } - ui.submit{ text = _"Save" } + + ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = area.name or _"New area" } + end ) + + ui.sectionRow( function() + + ui.field.hidden{ name = "unit_id", value = area.unit_id } + ui.field.text{ label = _"Unit", value = area.unit.name, readonly = true } + ui.field.text{ label = _"Name", name = "name" } + ui.field.text{ label = _"Description", name = "description", multiline = true } + ui.field.select{ label = _"Default Policy", name = "default_policy", + value=area.default_policy and area.default_policy.id or "-1", + foreign_records = def_policy, + foreign_id = "id", + foreign_name = "name" + } + ui.heading { level = 3, content = _"Allowed policies" } + ui.multiselect{ name = "allowed_policies[]", + foreign_records = policies, + foreign_id = "id", + foreign_name = "name", + connecting_records = area.allowed_policies or {}, + foreign_reference = "id", + } + slot.put("

") + ui.field.boolean{ label = _"Active?", name = "active", value = hint and true or nil } + ui.submit{ text = _"update area" } + slot.put(" ") + ui.link{ module = "admin", view = "index", content = _"cancel" } + end ) + end ) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/cancel_issue.lua --- a/app/main/admin/cancel_issue.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/cancel_issue.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,38 +1,39 @@ - local id = param.get("id") if not id then - ui.title("Cancel issue") - ui.actions() - ui.form{ - module = "admin", - view = "cancel_issue", - content = function() - ui.field.text{ label = _"Issue ID", name = "id" } - ui.submit{ text = _"Cancel issue" } - end - } -else - - local issue = Issue:by_id(id) - - ui.title(_("Cancel issue #{id}", { id = issue.id })) - ui.actions() + return +end + +local issue = Issue:by_id(id) +issue:load_everything_for_member_id ( app.session.member_id ) +issue.initiatives:load_everything_for_member_id ( app.session.member_id ) + +ui.titleAdmin(_"Cancel issue") +ui.form{ + module = "admin", + action = "cancel_issue", + id = id, + attr = { class = "vertical section" }, + content = function() - execute.view{ module = "initiative", view = "_list", params = { - initiatives_selector = issue:get_reference_selector("initiatives") - } } + ui.sectionHead( function() + ui.heading { level = 1, content = _("Cancel issue ##{id}", { id = issue.id }) } + end ) - ui.form{ - module = "admin", - action = "cancel_issue", - id = id, - attr = { class = "vertical" }, - content = function() - ui.field.text{ label = _"Public administrative notice:", name = "admin_notice", multiline = true } - ui.submit{ text = _"Cancel issue now" } - end - } + ui.sectionRow( function() + execute.view{ module = "initiative", view = "_list", params = { + issue = issue, + initiatives = issue.initiatives + } } + end ) + + ui.sectionRow( function() + ui.field.text{ label = _"public administrative notice:", name = "admin_notice", multiline = true } + ui.submit{ text = _"cancel issue now" } + slot.put(" ") + ui.link { module = "admin", view = "index", content = "go back to safety" } + end ) + end +} -end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/index.lua --- a/app/main/admin/index.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/index.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,34 +1,126 @@ -slot.put_into("title", _"Admin menu") +local units = Unit:get_flattened_tree{ active = true } +local policies = Policy:build_selector{}:add_order_by("index"):exec() + +slot.put_into("title", _"Manage system settings") +ui.sidebar( "tab-members", function() + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Members" } + end ) + + ui.sidebarSection( function() + ui.tag { tag = "ul", attr = { class = "ul" }, content = function() + ui.tag { tag = "li", content = function() + ui.form{ + module = "admin", view = "member_list", + content = function() + + ui.field.text{ label = _"search", name = "search" } + + ui.submit{ value = _"search" } + + end + } + end } + end } + end ) + ui.sidebarSection( "moreLink", function() + ui.link{ + text = _"Register new member", + module = "admin", + view = "member_edit" + } + end ) +end ) -ui.tag{ tag = "ul", content = function() - ui.tag{ tag= "li", content = function() +ui.sidebar( "tab-whatcanido", function() + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Cancel issue" } + end ) + + ui.sidebarSection( function() + ui.form{ + module = "admin", + view = "cancel_issue", + content = function() + ui.tag { tag = "ul", attr = { class = "ul" }, content = function() + ui.tag { tag = "li", content = function() + ui.field.text{ label = _"Issue #", name = "id" } + ui.submit{ text = _"cancel issue" } + end } + end } + end + } + end ) +end ) + +ui.sidebar("tab-whatcanido", function() + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Policies" } + end ) + + ui.sidebarSection( function() + ui.tag { tag = "ul", attr = { class = "ul" }, content = function() + for i, policy in ipairs(policies) do + ui.tag { tag = "li", content = function() + ui.link{ + content = policy.name, + module = "admin", + view = "policy_show", + id = policy.id + } + end } + end + end } + end ) + ui.sidebarSection( "moreLink", function() ui.link{ - text = _"Policies", + text = _"Create new policy", + module = "admin", + view = "policy_show" + } + end ) + ui.sidebarSection( "moreLink", function() + ui.link{ + text = _"Show policies not in use", module = "admin", view = "policy_list", - } - end } - ui.tag{ tag= "li", content = function() - ui.link{ - text = _"Units", - module = "admin", - view = "unit_list", + params = { show_not_in_use = true } } - end } - ui.tag{ tag= "li", content = function() - ui.link{ - text = _"Members", - module = "admin", - view = "member_list", - } - end } - ui.tag{ tag= "li", content = function() - ui.link{ - text = _"Cancel issue", - module = "admin", - view = "cancel_issue", - } - end } -end } + end ) +end ) + + +ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = _"Organizational units and subject areas" } + end ) + ui.sectionRow( function() + for i_unit, unit in ipairs(units) do + ui.container { + attr = { style = "margin-left: " .. ((unit.depth - 1)* 2) .. "em;" }, + content = function () + ui.heading { level = 1, content = function () + ui.link{ text = unit.name, module = "admin", view = "unit_edit", id = unit.id } + end } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + for i, area in ipairs(unit:get_reference_selector("areas"):add_order_by("name"):exec()) do + ui.tag { tag = "li", content = function () + ui.link{ text = area.name, module = "admin", view = "area_show", id = area.id } + end } + end + ui.tag { tag = "li", content = function () + ui.link { module = "admin", view = "area_show", params = { unit_id = unit.id }, content = _"+ add new subject area" } + end } + slot.put("
") + end } + end + } + end + + slot.put("
") + ui.link { module = "admin", view = "unit_edit", content = _"+ add new organizational unit" } + + end) +end) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/member_edit.lua --- a/app/main/admin/member_edit.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/member_edit.lua Thu Jul 10 01:19:48 2014 +0200 @@ -2,11 +2,7 @@ local member = Member:by_id(id) -if member then - ui.title(_("Member: '#{identification}' (#{name})", { identification = member.identification, name = member.name })) -else - ui.title(_"Register new member") -end +ui.title(_"member") local units_selector = Unit:new_selector() @@ -19,7 +15,7 @@ local units = units_selector:exec() ui.form{ - attr = { class = "vertical" }, + attr = { class = "vertical section" }, module = "admin", action = "member_update", id = member and member.id, @@ -29,43 +25,54 @@ default = { mode = "redirect", modules = "admin", - view = "member_list" + view = "index" } }, content = function() - ui.field.text{ label = _"Identification", name = "identification" } - ui.field.text{ label = _"Notification email", name = "notify_email" } - if member and member.activated then - ui.field.text{ label = _"Screen name", name = "name" } - ui.field.text{ label = _"Login name", name = "login" } - end - ui.field.boolean{ label = _"Admin?", name = "admin" } - slot.put("
") - - for i, unit in ipairs(units) do - ui.field.boolean{ - name = "unit_" .. unit.id, - label = unit.name, - value = unit.voting_right + ui.sectionHead( function() + ui.heading { level = 1, content = member and member.name or _"New member" } + if member and member.identification then + ui.heading { level = 3, content = member.identification } + end + end ) + + ui.sectionRow( function() + ui.field.text{ label = _"Identification", name = "identification" } + ui.field.text{ label = _"Notification email", name = "notify_email" } + if member and member.activated then + ui.field.text{ label = _"Screen name", name = "name" } + ui.field.text{ label = _"Login name", name = "login" } + end + + for i, unit in ipairs(units) do + ui.field.boolean{ + name = "unit_" .. unit.id, + label = unit.name, + value = unit.voting_right + } + end + slot.put("

") + + if not member or not member.activated then + ui.field.boolean{ label = _"Send invite?", name = "invite_member" } + end + + if member and member.activated then + ui.field.boolean{ label = _"Lock member?", name = "locked" } + end + + ui.field.boolean{ + label = _"Member inactive?", name = "deactivate", + readonly = member and member.active, value = member and member.active == false } - end - slot.put("

") - - if not member or not member.activated then - ui.field.boolean{ label = _"Send invite?", name = "invite_member" } - end - - if member and member.activated then - ui.field.boolean{ label = _"Lock member?", name = "locked" } - end - - ui.field.boolean{ - label = _"Member inactive?", name = "deactivate", - readonly = member and member.active, value = member and member.active == false - } - - slot.put("
") - ui.submit{ text = _"Save" } + + slot.put("
") + ui.field.boolean{ label = _"Admin?", name = "admin" } + slot.put("
") + ui.submit{ text = _"update member" } + slot.put(" ") + ui.link { module = "admin", view = "index", content = _"cancel" } + end ) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/member_list.lua --- a/app/main/admin/member_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/member_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,96 +1,100 @@ local search = param.get("search") -ui.title(_"Member list") +ui.titleAdmin(_"Member list") + +ui.section( function() + + ui.sectionHead( function() + ui.heading { level = 1, content = _"Member list" } + end ) -ui.actions(function() - ui.link{ - attr = { class = { "admin_only" } }, - text = _"Register new member", - module = "admin", - view = "member_edit" - } -end) - - -ui.form{ - module = "admin", view = "member_list", - content = function() + ui.sectionRow( function () + ui.form{ + module = "admin", view = "member_list", + content = function() + + ui.field.text{ label = _"search", name = "search", value = search } + + ui.submit{ value = _"search" } + + end + } + end ) - ui.field.text{ label = _"Search for members", name = "search" } - - ui.submit{ value = _"Start search" } - - end -} -if not search then - return -end - -local members_selector = Member:build_selector{ - admin_search = search, - order = "identification" -} + ui.sectionRow( function () + local members_selector = Member:build_selector{ + admin_search = search, + order = "identification" + } -ui.paginate{ - selector = members_selector, - per_page = 30, - content = function() - ui.list{ - records = members_selector:exec(), - columns = { - { - field_attr = { style = "text-align: right;" }, - label = _"Id", - name = "id" - }, - { - label = _"Identification", - name = "identification" - }, - { - label = _"Screen name", - name = "name" - }, - { - label = _"Admin?", - content = function(record) - if record.admin then - ui.field.text{ value = "admin" } - end - end - }, - { - content = function(record) - if not record.activated then - ui.field.text{ value = "not activated" } - elseif not record.active then - ui.field.text{ value = "inactive" } - else - ui.field.text{ value = "active" } - end - end - }, - { - content = function(record) - if record.locked then - ui.field.text{ value = "locked" } - end - end - }, - { - content = function(record) - ui.link{ - attr = { class = "action admin_only" }, - text = _"Edit", - module = "admin", - view = "member_edit", - id = record.id - } - end + ui.paginate{ + selector = members_selector, + per_page = 30, + content = function() + ui.list{ + records = members_selector:exec(), + columns = { + { + label = _"Id", + content = function(record) + ui.link{ + text = record.id, + module = "admin", + view = "member_edit", + id = record.id + } + end + }, + { + label = _"Identification", + content = function(record) + ui.link{ + text = record.identification or "", + module = "admin", + view = "member_edit", + id = record.id + } + end + }, + { + label = _"Screen name", + content = function(record) + ui.link{ + text = record.name or "", + module = "admin", + view = "member_edit", + id = record.id + } + end + }, + { + content = function(record) + if record.admin then + ui.field.text{ value = "admin" } + end + end + }, + { + content = function(record) + if not record.activated then + ui.field.text{ value = "not activated" } + elseif not record.active then + ui.field.text{ value = "inactive" } + end + end + }, + { + content = function(record) + if record.locked then + ui.field.text{ value = "locked" } + end + end + }, + } } - } + end } - end -} \ No newline at end of file + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/policy_list.lua --- a/app/main/admin/policy_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/policy_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -3,52 +3,58 @@ local policies = Policy:build_selector{ active = not show_not_in_use }:exec() -ui.title(_"Policy list") +ui.titleAdmin(_"Policy list") +ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = _"Policy list" } + end ) + + ui.sectionRow( function() -ui.actions(function() + if show_not_in_use then + ui.link{ + text = _"Show policies in use", + module = "admin", + view = "policy_list" + } - if show_not_in_use then - ui.link{ - text = _"Show policies in use", - module = "admin", - view = "policy_list" + else + ui.link{ + text = _"Create new policy", + module = "admin", + view = "policy_show" + } + slot.put(" · ") + ui.link{ + text = _"Show policies not in use", + module = "admin", + view = "policy_list", + params = { show_not_in_use = true } + } + + end + + end ) + + ui.sectionRow( function() + + ui.list{ + records = policies, + columns = { + + { content = function(record) + ui.link{ + text = record.name, + module = "admin", + view = "policy_show", + id = record.id + } + end + } + + } } - else - ui.link{ - text = _"Create new policy", - module = "admin", - view = "policy_show" - } - slot.put(" · ") - ui.link{ - text = _"Show policies not in use", - module = "admin", - view = "policy_list", - params = { show_not_in_use = true } - } - - end - -end) - - -ui.list{ - records = policies, - columns = { - - { label = _"Policy", name = "name" }, - - { content = function(record) - ui.link{ - text = _"Edit", - module = "admin", - view = "policy_show", - id = record.id - } - end - } - - } -} \ No newline at end of file + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/policy_show.lua --- a/app/main/admin/policy_show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/policy_show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,59 +1,71 @@ local policy = Policy:by_id(param.get_id()) or Policy:new() -ui.title(_"Create / edit policy") +local hint = not policy.id + +ui.titleAdmin(policy.name or _"New policy") + +ui.section( function() -ui.form{ - attr = { class = "vertical" }, - record = policy, - module = "admin", - action = "policy_update", - routing = { - default = { - mode = "redirect", + ui.sectionHead( function() + ui.heading { level = 1, content = _"Policy" } + end ) + ui.sectionRow( function() + ui.form{ + attr = { class = "vertical" }, + record = policy, module = "admin", - view = "policy_list" - } - }, - id = policy.id, - content = function() + action = "policy_update", + routing = { + default = { + mode = "redirect", + module = "admin", + view = "index" + } + }, + id = policy.id, + content = function() - ui.field.text{ label = _"Index", name = "index" } - - ui.field.text{ label = _"Name", name = "name" } - ui.field.text{ label = _"Description", name = "description", multiline = true } - ui.field.text{ label = _"Hint", readonly = true, - value = _"Interval format:" .. " 3 mons 2 weeks 1 day 10:30:15" } + ui.field.text{ label = _"Index", name = "index", value = hint and "1" or nil } - ui.field.text{ label = _"Admission time", name = "admission_time" } - ui.field.text{ label = _"Discussion time", name = "discussion_time" } - ui.field.text{ label = _"Verification time", name = "verification_time" } - ui.field.text{ label = _"Voting time", name = "voting_time" } + ui.field.text{ label = _"Name", name = "name" } + ui.field.text{ label = _"Description", name = "description", multiline = true } + ui.field.text{ label = _"Hint", readonly = true, + value = _"Interval format:" .. " 3 mons 2 weeks 1 day 10:30:15" } - ui.field.text{ label = _"Issue quorum numerator", name = "issue_quorum_num" } - ui.field.text{ label = _"Issue quorum denumerator", name = "issue_quorum_den" } + ui.field.text{ label = _"Admission time", name = "admission_time", value = hint and "30 days" or nil } + ui.field.text{ label = _"Discussion time", name = "discussion_time", value = hint and "30 days" or nil } + ui.field.text{ label = _"Verification time", name = "verification_time", value = hint and "15 days" or nil } + ui.field.text{ label = _"Voting time", name = "voting_time", value = hint and "15 days" or nil } - ui.field.text{ label = _"Initiative quorum numerator", name = "initiative_quorum_num" } - ui.field.text{ label = _"Initiative quorum denumerator", name = "initiative_quorum_den" } + ui.field.text{ label = _"Issue quorum numerator", name = "issue_quorum_num", value = hint and "10" or nil } + ui.field.text{ label = _"Issue quorum denominator", name = "issue_quorum_den", value = hint and "100" or nil } + + ui.field.text{ label = _"Initiative quorum numerator", name = "initiative_quorum_num", value = hint and "10" or nil } + ui.field.text{ label = _"Initiative quorum denominator", name = "initiative_quorum_den", value = hint and "100" or nil } - ui.field.text{ label = _"Direct majority numerator", name = "direct_majority_num" } - ui.field.text{ label = _"Direct majority denumerator", name = "direct_majority_den" } - ui.field.boolean{ label = _"Strict direct majority", name = "direct_majority_strict" } - ui.field.text{ label = _"Direct majority positive", name = "direct_majority_positive" } - ui.field.text{ label = _"Direct majority non negative", name = "direct_majority_non_negative" } + ui.field.text{ label = _"Direct majority numerator", name = "direct_majority_num", value = hint and "50" or nil } + ui.field.text{ label = _"Direct majority denominator", name = "direct_majority_den", value = hint and "100" or nil } + ui.field.boolean{ label = _"Strict direct majority", name = "direct_majority_strict", value = hint and true or nil } + ui.field.text{ label = _"Direct majority positive", name = "direct_majority_positive", value = hint and "0" or nil } + ui.field.text{ label = _"Direct majority non negative", name = "direct_majority_non_negative", value = hint and "0" or nil } - ui.field.text{ label = _"Indirect majority numerator", name = "indirect_majority_num" } - ui.field.text{ label = _"Indirect majority denumerator", name = "indirect_majority_den" } - ui.field.boolean{ label = _"Strict indirect majority", name = "indirect_majority_strict" } - ui.field.text{ label = _"Indirect majority positive", name = "indirect_majority_positive" } - ui.field.text{ label = _"Indirect majority non negative", name = "indirect_majority_non_negative" } + ui.field.text{ label = _"Indirect majority numerator", name = "indirect_majority_num", value = hint and "50" or nil } + ui.field.text{ label = _"Indirect majority denominator", name = "indirect_majority_den", value = hint and "100" or nil } + ui.field.boolean{ label = _"Strict indirect majority", name = "indirect_majority_strict", value = hint and true or nil } + ui.field.text{ label = _"Indirect majority positive", name = "indirect_majority_positive", value = hint and "0" or nil } + ui.field.text{ label = _"Indirect majority non negative", name = "indirect_majority_non_negative", value = hint and "0" or nil } - ui.field.boolean{ label = _"No reverse beat path", name = "no_reverse_beat_path" } - ui.field.boolean{ label = _"No multistage majority", name = "no_multistage_majority" } - ui.field.boolean{ label = _"Polling mode", name = "polling" } + ui.field.boolean{ label = _"No reverse beat path", name = "no_reverse_beat_path", value = hint and false or nil } + ui.field.boolean{ label = _"No multistage majority", name = "no_multistage_majority", value = hint and false or nil } + ui.field.boolean{ label = _"Polling mode", name = "polling", value = hint and false or nil } - ui.field.boolean{ label = _"Active?", name = "active" } + ui.field.boolean{ label = _"Active?", name = "active", value = hint and true or nil } - ui.submit{ text = _"Save" } - end -} + ui.submit{ text = _"update policy" } + slot.put(" ") + ui.link { module = "admin", view = "index", content = _"cancel" } + end + } + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/admin/unit_edit.lua --- a/app/main/admin/unit_edit.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/admin/unit_edit.lua Thu Jul 10 01:19:48 2014 +0200 @@ -3,9 +3,7 @@ local unit = Unit:by_id(id) if unit then - ui.title(_("Unit: '#{name}'", { name = unit.name })) -else - ui.title(_"Add new unit") + ui.titleAdmin(_"Organizational unit") end local units = { @@ -17,7 +15,7 @@ end ui.form{ - attr = { class = "vertical" }, + attr = { class = "vertical section" }, module = "admin", action = "unit_update", id = unit and unit.id, @@ -26,22 +24,29 @@ default = { mode = "redirect", modules = "admin", - view = "unit_list" + view = "index" } }, content = function() - ui.field.select{ - label = _"Parent unit", - name = "parent_id", - foreign_records = units, - foreign_id = "id", - foreign_name = "name" - } - ui.field.text{ label = _"Name", name = "name" } - ui.field.text{ label = _"Description", name = "description", multiline = true } - ui.field.boolean{ label = _"Active?", name = "active" } + ui.sectionHead( function() + ui.heading { level = 1, content = unit and unit.name or _"New organizational unit" } + end ) + ui.sectionRow( function() + ui.field.select{ + label = _"Parent unit", + name = "parent_id", + foreign_records = units, + foreign_id = "id", + foreign_name = "name" + } + ui.field.text{ label = _"Name", name = "name" } + ui.field.text{ label = _"Description", name = "description", multiline = true } + ui.field.boolean{ label = _"Active?", name = "active" } - slot.put("
") - ui.submit{ text = _"Save" } + slot.put("
") + ui.submit{ text = _"update unit" } + slot.put(" ") + ui.link{ module = "admin", view = "index", content = _"cancel" } + end ) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/area/_head.lua --- a/app/main/area/_head.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/area/_head.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,110 +1,39 @@ local area = param.get("area", "table") local member = param.get("member", "table") -local show_content = param.get("show_content", atom.boolean) +ui.title ( function () -if app.session.member_id then - area:load_delegation_info_once_for_member_id(app.session.member_id) -end + -- unit link + ui.link { + attr = { class = "unit" }, + content = function() + ui.tag{ attr = { class = "name" }, content = area.unit.name } + end, + module = "unit", view = "show", + id = area.unit.id + } -if not param.get("hide_unit", atom.boolean) then - execute.view{ module = "unit", view = "_head", params = { unit = area.unit, member = member } } -end + ui.tag { attr = { class = "spacer" }, content = function() + slot.put ( " » " ) + end } -ui.container{ attr = { class = "area_head" }, content = function() - - execute.view{ module = "delegation", view = "_info", params = { area = area, member = member } } + ui.tag { attr = { class = "area" }, content = function() + -- area link + ui.link { + content = function() + ui.tag{ attr = { class = "name" }, content = area.name } + end, + module = "area", view = "show", + id = area.id + } + + slot.put ( " " ) - ui.container{ attr = { class = "title" }, content = function() - -- area name - ui.link{ - module = "area", view = "show", id = area.id, - attr = { class = "area_name" }, content = area.name + execute.view { + module = "delegation", view = "_info", params = { + area = area, member = member, for_title = true + } } end } - if show_content then - - ui.container{ attr = { class = "content" }, content = function() - - -- actions (members with appropriate voting right only) - if member then - - -- membership - local membership = Membership:by_pk(area.id, member.id) - - if membership then - - if app.session.member_id == member.id then - ui.tag{ content = _"You are participating in this area" } - slot.put(" ") - ui.tag{ content = function() - slot.put("(") - ui.link{ - text = _"Withdraw", - module = "membership", - action = "update", - params = { area_id = 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() - } - } - } - slot.put(")") - end } - else - ui.tag{ content = _"Member is participating in this area" } - end - - elseif app.session.member_id == member.id and member:has_voting_right_for_unit_id(area.unit_id) then - ui.link{ - text = _"Participate in this area", - module = "membership", - action = "update", - params = { area_id = area.id }, - routing = { - default = { - mode = "redirect", - module = request.get_module(), - view = request.get_view(), - id = param.get_id_cgi(), - params = param.get_all_cgi() - } - } - } - end - - if app.session.member_id == member.id and app.session.member:has_voting_right_for_unit_id(area.unit_id) then - - slot.put(" · ") - if area.delegation_info.own_delegation_scope ~= "area" then - ui.link{ text = _"Delegate area", module = "delegation", view = "show", params = { area_id = area.id } } - else - ui.link{ text = _"Change area delegation", module = "delegation", view = "show", params = { area_id = area.id } } - end - slot.put(" · ") - - ui.link{ - content = function() - slot.put(_"Create new issue") - end, - module = "initiative", - view = "new", - params = { area_id = area.id } - } - end - - end - - end } - - else - slot.put("
") - end - -end } \ No newline at end of file +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/area/_issue_list.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/area/_issue_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,43 @@ +local issues_selector = param.get("issues_selector", "table") +local phase = param.get("phase") + +if phase == "admission" then + headline = _"Issues in admission phase" +elseif phase == "discussion" then + headline = _"Issues in discussion phase" +elseif phase == "verification" then + headline = _"Issues in verification phase" +elseif phase == "voting" then + headline = _"Issues in voting phase" +elseif phase == "closed" then + headline = _"Closed issues" +end + +ui.heading { level = "1", content = headline } + +local issues = issues_selector:exec() + +ui.tag { + tag = "ul", + attr = { class = { "issues" } }, + content = function () + + for i, issue in ipairs(issues) do + + ui.tag { tag = "li", content = function () + ui.heading { level = 2, content = issue.name } + + execute.view { + module = "initiative", view = "_list", params = { + initiatives = issue.initiatives, + state = phase + } + } + + slot.put ( '
' ) + + end } + + end + end +} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/area/_sidebar_members.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/area/_sidebar_members.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,33 @@ +if not app.session:has_access("all_pseudonymous") then + return +end + +local area = param.get("area", "table") +local members_selector = Member:new_selector() + :join("membership", nil, { "membership.member_id = member.id AND membership.area_id = ?", area.id }) + :add_where("member.active") + :limit(50) + +ui.sidebar ( "tab-members", function () + ui.sidebarHead( function () + ui.heading { + level = 2, + content = _("Subscribed members (#{count})", { + count = area.direct_member_count + }) + } + end ) + execute.view { + module = 'member', view = '_list', params = { + members_selector = members_selector, + no_filter = true, no_paginate = true, + member_class = "sidebarRow sidebarRowNarrow" + } + } + if area.direct_member_count > members_selector:count() then + ui.link { + text = _"Show all members", + module = "member", view = "list" + } + end +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/area/_sidebar_whatcanido.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/area/_sidebar_whatcanido.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,168 @@ +local member = param.get ( "member", "table" ) or app.session.member + +local area = param.get ( "area", "table" ) + +local participating_trustee_id +local participating_trustee_name +if member then + if area.delegation_info.first_trustee_participation then + participating_trustee_id = area.delegation_info.first_trustee_id + participating_trustee_name = area.delegation_info.first_trustee_name + elseif area.delegation_info.other_trustee_participation then + participating_trustee_id = area.delegation_info.other_trustee_id + participating_trustee_name = area.delegation_info.other_trustee_name + end +end + +ui.sidebar ( "tab-whatcanido", function () + + ui.sidebarHeadWhatCanIDo() + + if member and not app.session.member:has_voting_right_for_unit_id(area.unit_id) then + ui.sidebarSection( _"You are not entitled to vote in this unit" ) + end + + if member and app.session.member:has_voting_right_for_unit_id(area.unit_id) then + if not area.delegation_info.own_participation then + ui.sidebarSection ( function () + + ui.heading { + level = 3, + content = _"I want to participate in this subject area" + } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = function () + ui.link { + module = "membership", action = "update", + routing = { default = { + mode = "redirect", module = "area", view = "show", id = area.id + } }, + params = { area_id = area.id }, + text = _"subscribe" + } + end } + end } + end } + end ) + end + + if area.delegation_info.own_participation then + ui.sidebarSection ( function () + ui.image{ attr = { class = "right" }, static = "icons/48/star.png" } + ui.heading { + level = 3, + content = _"You are subscribed for this subject area" + } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = function () + ui.link { + module = "membership", action = "update", + routing = { default = { + mode = "redirect", module = "area", view = "show", id = area.id + } }, + params = { area_id = area.id, delete = true }, + text = _"unsubscribe" + } + end } + end } + end } + end ) + end + + + ui.sidebarSection ( function () + + + if not area.delegation_info.first_trustee_id then + ui.heading{ level = 3, content = _"I want to delegate this subject area" } + else + ui.container { attr = { class = "right" }, content = function() + local member = Member:by_id(area.delegation_info.first_trustee_id) + execute.view{ + module = "member_image", + view = "_show", + params = { + member = member, + image_type = "avatar", + show_dummy = true + } + } + end } + ui.heading{ level = 3, content = _"You delegated this subject area" } + end + + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + if area.delegation_info.own_delegation_scope == "unit" then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + unit_id = area.unit_id, + }, + content = _("change/revoke delegation of organizational unit") + } + end } + end + + if area.delegation_info.own_delegation_scope == nil then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + area_id = area.id + }, + content = _"choose subject area delegatee" + } + end } + elseif area.delegation_info.own_delegation_scope == "area" then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + area_id = area.id + }, + content = _"change/revoke area delegation" + } + end } + else + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + area_id = area.id + }, + content = _"change/revoke delegation only for this subject area" + } + end } + end + end } + end ) + + + + + if app.session.member:has_voting_right_for_unit_id ( area.unit_id ) then + ui.sidebarSection ( function () + ui.heading { + level = 3, + content = _("I want to start a new initiative", { + area_name = area.name + } ) + } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = _"Take a look through the existing issues. Maybe someone else started a debate on your topic (and you can join it) or the topic has been decided already in the past." } + ui.tag { tag = "li", content = function () + ui.tag { content = function () + ui.tag { content = _"If you cannot find any appropriate existing issue, " } + ui.link { + module = "initiative", view = "new", + params = { area_id = area.id }, + text = _"start an initiative in a new issue" + } + end } + end } + end } + end ) + end + else + end + +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/area/show.lua --- a/app/main/area/show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/area/show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,27 +1,53 @@ local area = Area:by_id(param.get_id()) +if not area then + execute.view { module = "index", view = "404" } + request.set_status("404 Not Found") + return +end + +area:load_delegation_info_once_for_member_id(app.session.member_id) app.html_title.title = area.name app.html_title.subtitle = _("Area") -util.help("area.show") - -slot.select("head", function() - execute.view{ module = "area", view = "_head", params = { area = area, show_content = true, member = app.session.member } } -end) +execute.view { + module = "area", view = "_head", params = { + area = area, member = app.session.member + } +} -ui.container{ - attr = { class = "vertical"}, - content = function() - ui.field.text{ value = area.description } - end +execute.view { + module = "area", view = "_sidebar_whatcanido", params = { + area = area + } +} + +execute.view { + module = "area", view = "_sidebar_members", params = { + area = area + } } -local open_issues_selector = area:get_reference_selector("issues") - :add_where("issue.closed ISNULL") - :add_order_by("coalesce(issue.fully_frozen + issue.voting_time, issue.half_frozen + issue.verification_time, issue.accepted + issue.discussion_time, issue.created + issue.admission_time) - now()") +function getOpenIssuesSelector() + return area:get_reference_selector("issues") + :add_order_by("coalesce(issue.fully_frozen + issue.voting_time, issue.half_frozen + issue.verification_time, issue.accepted + issue.discussion_time, issue.created + issue.admission_time) - now()") +end + +local admission_selector = getOpenIssuesSelector() + :add_where("issue.state = 'admission'"); -local closed_issues_selector = area:get_reference_selector("issues") +local discussion_selector = getOpenIssuesSelector() + :add_where("issue.state = 'discussion'"); + +local verification_selector = getOpenIssuesSelector() + :add_where("issue.state = 'verification'"); + +local voting_selector = getOpenIssuesSelector() + :add_where("issue.state = 'voting'"); + + +local closed_selector = area:get_reference_selector("issues") :add_where("issue.closed NOTNULL") :add_order_by("issue.closed DESC") @@ -30,61 +56,9 @@ :join("member", "truster", "truster.id = delegation.truster_id AND truster.active") :join("member", "trustee", "trustee.id = delegation.trustee_id AND trustee.active") -local tabs = { - module = "area", - view = "show_tab", - static_params = { area_id = area.id }, -} -tabs[#tabs+1] = { - name = "timeline", - label = _"Latest events", - module = "event", - view = "_list", +execute.view { + module = "issue", + view = "_list2", params = { for_area = area } } - -tabs[#tabs+1] = { - name = "open", - label = _"Open issues", - module = "issue", - view = "_list", - params = { - for_state = "open", - issues_selector = open_issues_selector, for_area = true - } -} -tabs[#tabs+1] = { - name = "closed", - label = _"Closed issues", - module = "issue", - view = "_list", - params = { - for_state = "closed", - issues_selector = closed_issues_selector, for_area = true - } -} - -if app.session:has_access("all_pseudonymous") then - tabs[#tabs+1] = - { - name = "members", - label = _"Participants" .. " (" .. tostring(members_selector:count()) .. ")", - icon = { static = "icons/16/group.png" }, - module = "member", - view = "_list", - params = { members_selector = members_selector } - } - - tabs[#tabs+1] = - { - name = "delegations", - label = _"Delegations" .. " (" .. tostring(delegations_selector:count()) .. ")", - icon = { static = "icons/16/table_go.png" }, - module = "delegation", - view = "_list", - params = { delegations_selector = delegations_selector } - } -end - -ui.tabs(tabs) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/contact/list.lua --- a/app/main/contact/list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/contact/list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -6,9 +6,6 @@ ui.title(_"Contacts") -util.help("contact.list") - - ui.paginate{ selector = contacts_selector, content = function() diff -r a6c7bf07badb -r 701a5cf6b067 app/main/delegation/_info.lua --- a/app/main/delegation/_info.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/delegation/_info.lua Thu Jul 10 01:19:48 2014 +0200 @@ -8,6 +8,8 @@ local area = param.get("area", "table") local issue = param.get("issue", "table") +local for_title = param.get("for_title", "boolean") + local unit_id = unit and unit.id or nil local area_id = area and area.id or nil local issue_id = issue and issue.id or nil @@ -21,7 +23,6 @@ end if area then - area:load_delegation_info_once_for_member_id(member.id) info = area.delegation_info delegation_text = _"Delegate area" end @@ -31,24 +32,13 @@ delegation_text = _"Delegate issue" end +if not info then + --return +end + local function print_delegation_info() - local participant_occured = false + local participant_occured = info.own_participation - if info.own_participation or info.first_trustee_id then - - local class = "micro_avatar" - if info.own_participation then - participant_occured = true - class = class .. " highlighted" - end - - execute.view{ module = "member_image", view = "_show", params = { - member = member, class = class, popup_text = member.name, - image_type = "avatar", show_dummy = true, - } } - - end - if not (issue and issue.state == "voting" and info.own_participation) then if info.first_trustee_id then @@ -154,10 +144,15 @@ static = "delegation_arrow_24_horizontal.png" } - execute.view{ module = "member_image", view = "_show", params = { - member_id = info.first_trustee_id, class = "micro_avatar", popup_text = info.first_trustee_name, - image_type = "avatar", show_dummy = true, - } } + execute.view{ + module = "member_image", view = "_show", params = { + member_id = info.first_trustee_id, + class = "micro_avatar", + popup_text = info.first_trustee_name, + image_type = "avatar", + show_dummy = true, + } + } end @@ -174,24 +169,94 @@ end end +if not param.get("no_star", "boolean") then + + if info.own_participation then + if issue and issue.fully_frozen then + ui.link{ + attr = { class = "right" }, + module = "vote", view = "list", params = { + issue_id = issue.id + }, + content = function () + ui.tag { content = _"you voted" } + end + } + else + if issue then + local text = _"you are interested" + ui.image { attr = { class = "star", title = text, alt = text }, static = "icons/48/eye.png" } + if not issue.closed and info.own_participation and info.weight and info.weight > 1 then + ui.link { + attr = { class = "right" }, content = "+" .. (info.weight - 1), + module = "delegation", view = "show_incoming", params = { + issue_id = issue.id, member_id = member.id + } + } + end + else + local text = _"you are subscribed" + ui.image { attr = { class = "icon24 star", title = text, alt = text }, static = "icons/48/star.png" } + end + if not for_title then + slot.put("
") + else + slot.put(" ") + end + end + end +end + if info.own_participation or info.first_trustee_id then + local class = "delegation_info" + if info.own_participation then + class = class .. " suspended" + end + + local voting_member_id + local voting_member_name + if issue and issue.fully_frozen and issue.closed then + if issue.member_info.first_trustee_participation then + voting_member_id = issue.member_info.first_trustee_id + voting_member_name = issue.member_info.first_trustee_name + elseif issue.member_info.other_trustee_participation then + voting_member_id = issue.member_info.other_trustee_id + voting_member_name = issue.member_info.other_trustee_name + end + end + if app.session.member_id == member.id then - ui.link{ - module = "delegation", view = "show", params = { - unit_id = unit_id, - area_id = area_id, - issue_id = issue_id - }, - attr = { class = "delegation_info" }, content = function() - print_delegation_info() - end - } + + if voting_member_id then + ui.link{ + module = "vote", view = "list", params = { + issue_id = issue.id, + member_id = voting_member_id + }, + attr = { class = class }, content = function() + print_delegation_info() + end + } + + else + ui.link{ + module = "delegation", view = "show", params = { + unit_id = unit_id, + area_id = area_id, + issue_id = issue_id + }, + attr = { class = class }, content = function() + print_delegation_info() + end + } + end else ui.container{ - attr = { class = "delegation_info" }, content = function() + attr = { class = class }, content = function() print_delegation_info() end } end end + diff -r a6c7bf07badb -r 701a5cf6b067 app/main/delegation/_list.lua --- a/app/main/delegation/_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/delegation/_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -3,83 +3,84 @@ local incoming = param.get("incoming", atom.boolean) local function delegation_scope(delegation) - ui.container{ + ui.tag{ attr = { class = "delegation_scope" }, content = function() local area local unit if delegation.issue then area = delegation.issue.area + unit = area.unit elseif delegation.area then area = delegation.area + unit = area.unit else unit = delegation.unit end - if unit then + slot.put("
") + ui.heading { attr = { style = "float: left;" }, level = 3, content = function() ui.link{ - content = _"Unit '#{name}'":gsub("#{name}", unit.name), + content = unit.name, module = "unit", view = "show", id = unit.id } - end - if area then - ui.link{ - content = _"Area '#{name}'":gsub("#{name}", area.name), - module = "area", - view = "show", - id = area.id - } - end - if delegation.issue then - ui.link{ - content = _"Issue ##{id}":gsub("#{id}", delegation.issue.id), - module = "issue", - view = "show", - id = delegation.issue.id - } - end + if area then + slot.put(" · ") + ui.link{ + content = area.name, + module = "area", + view = "show", + id = area.id + } + end + if delegation.issue then + slot.put(" · ") + ui.link{ + content = delegation.issue.name, + module = "issue", + view = "show", + id = delegation.issue.id + } + end + end } end } end -ui.paginate{ - selector = delegations_selector, - content = function() +--ui.paginate{ +-- selector = delegations_selector, +-- name = incoming and "delegation_incoming" or "delegation_outgoing", +-- content = function() + local last_scope = {} for i, delegation in ipairs(delegations_selector:exec()) do - ui.container{ - attr = { class = "delegation_list_entry" }, - content = function() - if outgoing then - delegation_scope(delegation) - else - execute.view{ - module = "member", - view = "_show_thumb", - params = { member = delegation.truster } - } - end - ui.image{ - attr = { class = "delegation_arrow" }, - static = "delegation_arrow.jpg" - } - if incoming then - delegation_scope(delegation) - else - if delegation.trustee then - execute.view{ - module = "member", - view = "_show_thumb", - params = { member = delegation.trustee } - } - else - ui.tag{ content = _"Delegation abandoned" } - end - end - end - } + if last_scope.unit_id ~= delegation.unit_id + or last_scope.area_id ~= delegation.area_id + or last_scope.issue_id ~= delegation.issue_id + then + last_scope.unit_id = delegation.unit_id + last_scope.area_id = delegation.area_id + last_scope.issue_id = delegation.issue_id + delegation_scope(delegation) + end + if incoming then + execute.view{ module = "member_image", view = "_show", params = { + member_id = delegation.truster_id, class = "micro_avatar", popup_text = delegation.truster.name, + image_type = "avatar", show_dummy = true, + } } + elseif delegation.trustee then + ui.image{ + attr = { class = "delegation_arrow" }, + static = "delegation_arrow_24_horizontal.png" + } + execute.view{ module = "member_image", view = "_show", params = { + member_id = delegation.trustee_id, class = "micro_avatar", popup_text = delegation.trustee.name, + image_type = "avatar", show_dummy = true, + } } + else + ui.tag{ content = _"Delegation abandoned" } + end end - slot.put("
") - end -} +-- end +--} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/delegation/show.lua --- a/app/main/delegation/show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/delegation/show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -2,7 +2,17 @@ local current_trustee_id local current_trustee_name +local head_text + local unit = Unit:by_id(param.get("unit_id", atom.integer)) +local area = Area:by_id(param.get("area_id", atom.integer)) +local issue = Issue:by_id(param.get("issue_id", atom.integer)) +local initiative = Initiative:by_id(param.get("initiative_id", atom.integer)) + +if initiative then + issue = initiative.issue +end + if unit then unit:load_delegation_info_once_for_member_id(app.session.member_id) voting_right_unit_id = unit.id @@ -10,11 +20,10 @@ current_trustee_id = unit.delegation_info.first_trustee_id current_trustee_name = unit.delegation_info.first_trustee_name end - ui.title(config.single_unit_id and _"Set global delegation" or _"Set unit delegation") - util.help("delegation.new.unit") + execute.view { module = "unit", view = "_head", params = { unit = unit } } + head_text = _"Set unit delegation" end -local area = Area:by_id(param.get("area_id", atom.integer)) if area then area:load_delegation_info_once_for_member_id(app.session.member_id) voting_right_unit_id = area.unit_id @@ -22,11 +31,10 @@ current_trustee_id = area.delegation_info.first_trustee_id current_trustee_name = area.delegation_info.first_trustee_name end - ui.title(_"Set delegation for Area '#{name}'":gsub("#{name}", area.name)) - util.help("delegation.new.area") + execute.view { module = "area", view = "_head", params = { area = area } } + head_text = _"Set area delegation" end -local issue = Issue:by_id(param.get("issue_id", atom.integer)) if issue then issue:load("member_info", { member_id = app.session.member_id }) voting_right_unit_id = issue.area.unit_id @@ -34,8 +42,13 @@ current_trustee_id = issue.member_info.first_trustee_id current_trustee_name = issue.member_info.first_trustee_name end - ui.title(_"Set delegation for Issue ##{number} in Area '#{area_name}'":gsub("#{number}", issue.id):gsub("#{area_name}", issue.area.name)) - util.help("delegation.new.issue") + execute.view { module = "issue", view = "_head", params = { issue = issue } } + head_text = _"Set issue delegation" +end + +if param.get("initiative_id", atom.integer) then + issue_id = initiative.issue_id + scope = "issue" end @@ -44,17 +57,16 @@ local area_id local issue_id local initiative_id -local initiative local scope = "unit" +local inline = param.get("inline", atom.boolean) + + unit_id = param.get("unit_id", atom.integer) -local inline = param.get("inline", atom.boolean) - if param.get("initiative_id", atom.integer) then - initiative_id = param.get("initiative_id", atom.integer) - initiative = Initiative:by_id(initiative_id) + initiative_id = initiative.id issue_id = initiative.issue_id scope = "issue" end @@ -106,177 +118,204 @@ ui.script{ static = "js/update_delegation_info.js" } -ui.actions(function() - if issue then - ui.link{ - module = "issue", - view = "show", - id = issue.id, - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - } - elseif area then - ui.link{ - module = "area", - view = "show", - id = area.id, - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - } - else - ui.link{ - module = "index", - view = "index", - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - } - end -end) + +ui.section( function () + + ui.sectionHead( function () + ui.heading{ level = 1, content = head_text } + end ) + + ui.sectionRow( function () - -ui.form{ - attr = { class = "vertical", id = "delegationForm" }, - module = "delegation", - action = "update", - params = { - unit_id = unit and unit.id or nil, - area_id = area and area.id or nil, - issue_id = issue and issue.id or nil, - initiative_id = initiative_id - }, - routing = { - default = { - mode = "redirect", - module = area and "area" or initiative and "initiative" or issue and "issue" or "unit", - view = "show", - id = area and area.id or initiative and initiative.id or issue and issue.id or unit.id, - } - }, - content = function() - local records - - if issue then - local delegate_name = "" - local scope = "no delegation set" - local area_delegation = Delegation:by_pk(app.session.member_id, nil, issue.area_id) - if area_delegation then - delegate_name = area_delegation.trustee and area_delegation.trustee.name or _"abandoned" - scope = _"area" - else - local unit_delegation = Delegation:by_pk(app.session.member_id, issue.area.unit_id) + ui.form{ + attr = { class = "wide section", id = "delegationForm" }, + module = "delegation", + action = "update", + params = { + unit_id = unit and unit.id or nil, + area_id = area and area.id or nil, + issue_id = issue and issue.id or nil, + initiative_id = initiative_id + }, + routing = { + default = { + mode = "redirect", + module = area and "area" or initiative and "initiative" or issue and "issue" or "unit", + view = "show", + id = area and area.id or initiative and initiative.id or issue and issue.id or unit.id, + } + }, + content = function() + local record + if issue then + local delegate_name = "" + local scope = "no delegation set" + local area_delegation = Delegation:by_pk(app.session.member_id, nil, issue.area_id) + if area_delegation then + delegate_name = area_delegation.trustee and area_delegation.trustee.name or _"abandoned" + scope = _"area" + else + local unit_delegation = Delegation:by_pk(app.session.member_id, issue.area.unit_id) + if unit_delegation then + delegate_name = unit_delegation.trustee.name + scope = config.single_unit_id and _"global" or _"unit" + end + end + local text_apply + local text_abandon + if config.single_unit_id then + text_apply = _("Apply global or area delegation for this issue (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) + text_abandon = _"Abandon unit and area delegations for this issue" + else + text_apply = _("Apply unit or area delegation for this issue (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) + text_abandon = _"Abandon unit and area delegations for this issue" + end + + records = { + { id = -1, name = text_apply }, + { id = 0, name = text_abandon } + } + elseif area then + local delegate_name = "" + local scope = "no delegation set" + local unit_delegation = Delegation:by_pk(app.session.member_id, area.unit_id) if unit_delegation then delegate_name = unit_delegation.trustee.name scope = config.single_unit_id and _"global" or _"unit" end - end - local text_apply - local text_abandon - if config.single_unit_id then - text_apply = _("Apply global or area delegation for this issue (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) - text_abandon = _"Abandon unit and area delegations for this issue" + local text_apply + local text_abandon + if config.single_unit_id then + text_apply = _("Apply global delegation for this area (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) + text_abandon = _"Abandon global delegation for this area" + else + text_apply = _("Apply unit delegation for this area (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) + text_abandon = _"Abandon unit delegation for this area" + end + records = { + { + id = -1, + name = text_apply + }, + { + id = 0, + name = text_abandon + } + } + else - text_apply = _("Apply unit or area delegation for this issue (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) - text_abandon = _"Abandon unit and area delegations for this issue" + records = { + { + id = -1, + name = _"No delegation" + } + } + end - records = { - { id = -1, name = text_apply }, - { id = 0, name = text_abandon } - } - elseif area then - local delegate_name = "" - local scope = "no delegation set" - local unit_delegation = Delegation:by_pk(app.session.member_id, area.unit_id) - if unit_delegation then - delegate_name = unit_delegation.trustee.name - scope = config.single_unit_id and _"global" or _"unit" + -- add current trustee + if current_trustee_id then + records[#records+1] = {id="_", name= "--- " .. _"Current delegatee" .. " ---"} + records[#records+1] = { id = current_trustee_id, name = current_trustee_name } + end + -- add initiative authors + if initiative then + records[#records+1] = {id="_", name= "--- " .. _"Initiators" .. " ---"} + for i,record in ipairs(initiative.initiators) do + records[#records+1] = record.member + end + end + -- add saved members + if #contact_members > 0 then + records[#records+1] = {id="_", name= "--- " .. _"Saved contacts" .. " ---"} + for i, record in ipairs(contact_members) do + records[#records+1] = record + end + end + + disabled_records = {} + disabled_records["_"] = true + disabled_records[app.session.member_id] = true + + local value = current_trustee_id + if preview_trustee_id then + value = preview_trustee_id + end + if preview_trustee_id == nil and delegation and not delegation.trustee_id then + value = 0 end - local text_apply - local text_abandon - if config.single_unit_id then - text_apply = _("Apply global delegation for this area (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) - text_abandon = _"Abandon global delegation for this area" + + ui.heading{ level = 2, content = _"Choose your delegatee" } + + ui.field.select{ + attr = { onchange = "updateDelegationInfo();" }, + name = "trustee_id", + foreign_records = records, + foreign_id = "id", + foreign_name = "name", + disabled_records = disabled_records, + value = value + } + + ui.container{ content = _"You can choose only members which you have been saved as contact before." } + + ui.field.hidden{ name = "preview" } + + slot.put("
") + ui.tag { tag = "input", content = "", attr = { + type = "submit", + value = _"Save", + class = "btn btn-default", + } } + + slot.put("


") + if initiative then + ui.link{ + module = "initiative", + view = "show", + id = initiative.id, + content = function() + slot.put(_"Cancel") + end, + } + elseif issue then + ui.link{ + module = "issue", + view = "show", + id = issue.id, + content = function() + slot.put(_"Cancel") + end, + } + elseif area then + ui.link{ + module = "area", + view = "show", + id = area.id, + content = function() + slot.put(_"Cancel") + end, + } else - text_apply = _("Apply unit delegation for this area (Currently: #{delegate_name} [#{scope}])", { delegate_name = delegate_name, scope = scope }) - text_abandon = _"Abandon unit delegation for this area" + ui.link{ + module = "index", + view = "index", + content = function() + slot.put(_"Cancel") + end, + } end - records = { - { - id = -1, - name = text_apply - }, - { - id = 0, - name = text_abandon - } - } - - else - records = { - { - id = -1, - name = _"No delegation" - } - } end - -- add current trustee - if current_trustee_id then - records[#records+1] = {id="_", name= "--- " .. _"Current trustee" .. " ---"} - records[#records+1] = { id = current_trustee_id, name = current_trustee_name } - end - -- add initiative authors - if initiative then - records[#records+1] = {id="_", name= "--- " .. _"Initiators" .. " ---"} - for i,record in ipairs(initiative.initiators) do - records[#records+1] = record.member - end - end - -- add saved members - if #contact_members > 0 then - records[#records+1] = {id="_", name= "--- " .. _"Saved contacts" .. " ---"} - for i, record in ipairs(contact_members) do - records[#records+1] = record - end - end + } - disabled_records = {} - disabled_records["_"] = true - disabled_records[app.session.member_id] = true +end ) end ) +-- ------------------------ - local value = current_trustee_id - if preview_trustee_id then - value = preview_trustee_id - end - if preview_trustee_id == nil and delegation and not delegation.trustee_id then - value = 0 - end - - ui.field.select{ - attr = { onchange = "updateDelegationInfo();" }, - label = _"Trustee", - name = "trustee_id", - foreign_records = records, - foreign_id = "id", - foreign_name = "name", - disabled_records = disabled_records, - value = value - } +ui.sidebar( "tab-members", function () - ui.field.hidden{ name = "preview" } - - ui.submit{ text = _"Save" } - - end -} - - --- ------------------------ +ui.sidebarHead( function () + ui.heading { level = 1, content = _"Preview of delegation" } +end ) local preview_inherit = false local tmp_preview_trustee_id = preview_trustee_id @@ -293,50 +332,58 @@ for i, record in ipairs(delegation_chain) do local style local overridden = (not issue or issue.state ~= 'voting') and record.overridden - if record.scope_in then - if not overridden then - ui.image{ - attr = { class = "delegation_arrow" }, - static = "delegation_arrow_24_vertical.png" - } - else - ui.image{ - attr = { class = "delegation_arrow delegation_arrow_overridden" }, - static = "delegation_arrow_24_vertical.png" + ui.sidebarSection( function () + if record.scope_in then + if not overridden then + local text = _"delegated to" + ui.image{ + attr = { class = "delegation_arrow", alt = text, title = text }, + static = "delegation_arrow_24_vertical.png" + } + else + local text = _"delegated to" + ui.image{ + attr = { class = "delegation_arrow delegation_arrow_overridden", alt = text, title = text }, + static = "delegation_arrow_24_vertical.png" + } + end + ui.tag{ + attr = { class = "delegation_scope" .. (overridden and " delegation_scope_overridden" or "") }, + content = function() + if record.scope_in == "unit" then + slot.put(config.single_object_mode and _"Global delegation" or _"Unit delegation") + elseif record.scope_in == "area" then + slot.put(_"Area delegation") + elseif record.scope_in == "issue" then + slot.put(_"Issue delegation") + end + end } end - ui.tag{ - attr = { class = "delegation_scope" .. (overridden and " delegation_scope_overridden" or "") }, + ui.container{ + attr = { class = overridden and "delegation_overridden" or "" }, content = function() - if record.scope_in == "unit" then - slot.put(config.single_object_mode and _"Global delegation" or _"Unit delegation") - elseif record.scope_in == "area" then - slot.put(_"Area delegation") - elseif record.scope_in == "issue" then - slot.put(_"Issue delegation") - end + execute.view{ + module = "member", + view = "_show_thumb", + params = { member = record } + } end } - end - ui.container{ - attr = { class = overridden and "delegation_overridden" or "" }, - content = function() - execute.view{ - module = "member", - view = "_show_thumb", - params = { member = record } + if issue and issue.state ~= 'voting' and record.participation and not record.overridden then + ui.container{ + attr = { class = "delegation_participation" }, + content = function() + if i == #delegation_chain then + ui.tag{ content = _"This member is currently participating in this issue." } + else + ui.tag{ content = _"This member is participating, the remaining delegation chain is suspended during discussing." } + end + end } end - } - if (not issue or issue.state ~= 'voting') and record.participation and not record.overridden then - ui.container{ - attr = { class = "delegation_participation" }, - content = function() - slot.put(_"This member is participating, the rest of delegation chain is suspended while discussing") - end - } - end - slot.put("
") + slot.put("
") + end ) end if preview_trustee_id == 0 or not preview_trustee_id == null and delegation and not delegation.trustee_id then @@ -350,3 +397,5 @@ end end + +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/delegation/show_incoming.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/delegation/show_incoming.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,35 @@ +local issue = Issue:by_id(param.get("issue_id", atom.integer)) + +local member = Member:by_id(param.get("member_id", atom.integer)) + +local members_selector = Member:new_selector() + :join("delegating_interest_snapshot", nil, "delegating_interest_snapshot.member_id = member.id") + :join("issue", nil, "issue.id = delegating_interest_snapshot.issue_id") + :add_where{ "delegating_interest_snapshot.issue_id = ?", issue.id } + :add_where{ "delegating_interest_snapshot.event = ?", issue.latest_snapshot_event } + :add_where{ "delegating_interest_snapshot.delegate_member_ids[1] = ?", member.id } + :add_field{ "delegating_interest_snapshot.weight" } + + +execute.view { + module = "issue", view = "_head", params = { + issue = issue + } +} + +ui.section( function() + + ui.sectionHead( function() + ui.heading{ level = 1, content = _("Incoming delegations for '#{member_name}'", { member_name = member.name } ) } + end) + + execute.view{ + module = "member", + view = "_list", + params = { + members_selector = members_selector, + issue = issue, + trustee = member + } + } +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/draft/_action/add.lua --- a/app/main/draft/_action/add.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/draft/_action/add.lua Thu Jul 10 01:19:48 2014 +0200 @@ -25,19 +25,24 @@ return false end -local formatting_engine = param.get("formatting_engine") +local formatting_engine +if config.enforce_formatting_engine then + formatting_engine = config.enforce_formatting_engine +else + formatting_engine = param.get("formatting_engine") -local formatting_engine_valid = false -for fe, dummy in pairs(config.formatting_engine_executeables) do - if formatting_engine == fe then - formatting_engine_valid = true + local formatting_engine_valid = false + for i, fe in pairs(config.formatting_engines) do + if formatting_engine == fe.id then + formatting_engine_valid = true + end + end + if not formatting_engine_valid then + error("invalid formatting engine!") end end -if not formatting_engine_valid then - error("invalid formatting engine!") -end -if param.get("preview") then +if param.get("preview") or param.get("edit") then return false end @@ -57,5 +62,5 @@ draft:render_content() -slot.put_into("notice", _"New draft has been added to initiative") +slot.put_into("notice", _"The initiative text has been updated") diff -r a6c7bf07badb -r 701a5cf6b067 app/main/draft/diff.lua --- a/app/main/draft/diff.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/draft/diff.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,13 +1,20 @@ local old_draft_id = param.get("old_draft_id", atom.integer) local new_draft_id = param.get("new_draft_id", atom.integer) +local initiative_id = param.get("initiative_id", atom.number) -if not old_draft_id or not new_draft_id then - slot.put( _"Please choose two versions of the draft to compare") - return -end - -if old_draft_id == new_draft_id then - slot.put( _"Please choose two different versions of the draft to compare") +if not old_draft_id + or not new_draft_id + or old_draft_id == new_draft_id +then + slot.reset_all() + slot.select("error", function() + ui.tag{ content = _"Please choose two different versions of the draft to compare" } + end ) + request.redirect{ + module = "draft", view = "list", params = { + initiative_id = initiative_id + } + } return end @@ -20,40 +27,46 @@ local old_draft = Draft:by_id(old_draft_id) local new_draft = Draft:by_id(new_draft_id) -execute.view{ - module = "draft", - view = "_head", - params = { draft = new_draft} +local initiative = new_draft.initiative + +if app.session.member then + initiative:load_everything_for_member_id(app.session.member_id) + initiative.issue:load_everything_for_member_id(app.session.member_id) +end + + +execute.view{ module = "issue", view = "_sidebar_state", params = { + initiative = initiative +} } + +execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = initiative.issue, + highlight_initiative_id = initiative.id + } } -ui.title(_"Diff") +execute.view { + module = "issue", view = "_sidebar_whatcanido", + params = { initiative = initiative } +} -if app.session.member_id and not new_draft.initiative.revoked then - local supporter = Supporter:new_selector():add_where{"member_id = ?", app.session.member_id}:count() - if supporter then - ui.container{ - attr = { class = "draft_updated_info" }, - content = function() - slot.put(_"The draft of this initiative has been updated!") - slot.put(" ") - ui.link{ - text = _"Refresh support to current draft", - module = "initiative", - action = "add_support", - id = new_draft.initiative.id, - routing = { - default = { - mode = "redirect", - module = "initiative", - view = "show", - id = new_draft.initiative.id - } - } - } - end - } - end -end +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = initiative.issue, initiative = initiative + } +} + + + +execute.view { + module = "issue", view = "_head", params = { + issue = initiative.issue + } +} + + local old_draft_content = string.gsub(string.gsub(old_draft.content, "\n", " ###ENTER###\n"), " ", "\n") local new_draft_content = string.gsub(string.gsub(new_draft.content, "\n", " ###ENTER###\n"), " ", "\n") @@ -111,17 +124,87 @@ end end -if not status then - ui.field.text{ value = _"The drafts do not differ" } -else - ui.container{ - tag = "div", - attr = { class = "diff" }, - content = function() - output = output:gsub("[^\n\r]+", function(line) - process_line(line) - end) +ui.section( function() + ui.sectionHead( function() + ui.link{ + module = "initiative", view = "show", id = initiative.id, + content = function () + ui.heading { + level = 1, + content = initiative.display_name + } + end + } + ui.heading{ level = 2, content = _("Comparision of revisions #{id1} and #{id2}", { + id1 = old_draft.id, + id2 = new_draft.id + } ) } + end ) + + if app.session.member_id and not new_draft.initiative.revoked then + local supporter = app.session.member:get_reference_selector("supporters") + :add_where{ "initiative_id = ?", new_draft.initiative_id } + :optional_object_mode() + :exec() + if supporter and supporter.draft_id ~= new_draft.id then + ui.sectionRow("draft_updated_info", function() + ui.container{ + attr = { class = "info" }, + content = _"The draft of this initiative has been updated!" + } + slot.put(" ") + ui.link{ + text = _"refresh my support", + module = "initiative", + action = "add_support", + id = new_draft.initiative.id, + params = { draft_id = new_draft.id }, + routing = { + default = { + mode = "redirect", + module = "initiative", + view = "show", + id = new_draft.initiative.id + } + } + } + + slot.put(" · ") + + ui.link{ + text = _"remove my support", + module = "initiative", + action = "remove_support", + id = new_draft.initiative.id, + routing = { + default = { + mode = "redirect", + module = "initiative", + view = "show", + id = new_draft.initiative.id + } + } + } + + end ) end - } -end + end + + ui.sectionRow( function() + if not status then + ui.field.text{ value = _"The drafts do not differ" } + else + ui.container{ + tag = "div", + attr = { class = "diff" }, + content = function() + output = output:gsub("[^\n\r]+", function(line) + process_line(line) + end) + end + } + end + + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/draft/list.lua --- a/app/main/draft/list.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -local initiative = Initiative:by_id(param.get("initiative_id", atom.number)) - -execute.view{ - module = "initiative", view = "_show", params = { - initiative = initiative, show_as_head = true - } -} - -ui.link{ - text = _"Back to initiative", - module = "initiative", view = "show", id = initiative.id -} - -slot.put("
") -slot.put("
") - -ui.form{ - method = "get", - module = "draft", - view = "diff", - content = function() - ui.list{ - records = initiative.drafts, - columns = { - { - label = _"Created at", - content = function(record) - ui.field.text{ readonly = true, value = format.timestamp(record.created) } - end - }, - { - label = _"Author", - content = function(record) - if record.author then - return record.author:ui_field_text() - end - end - }, - { - content = function(record) - ui.link{ - attr = { class = "action" }, - text = _"Show", - module = "draft", - view = "show", - id = record.id - } - end - }, - { - label = _"Compare", - content = function(record) - slot.put('') - slot.put('') - end - } - } - } - ui.submit{ text = _"Compare" } - end -} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/draft/new.lua --- a/app/main/draft/new.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/draft/new.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,24 +1,27 @@ -slot.put_into("title", _"Edit draft") +local initiative = Initiative:by_id(param.get("initiative_id")) +initiative:load_everything_for_member_id(app.session.member_id) +initiative.issue:load_everything_for_member_id(app.session.member_id) -local initiative = Initiative:by_id(param.get("initiative_id")) -ui.actions(function() - ui.link{ - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - module = "initiative", - view = "show", - id = initiative.id +execute.view{ + module = "issue", view = "_head", params = { + issue = initiative.issue, + initiative = initiative } -end) +} + +execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = initiative.issue, + } +} ui.form{ record = initiative.current_draft, - attr = { class = "vertical" }, + attr = { class = "vertical section" }, module = "draft", action = "add", params = { initiative_id = initiative.id }, @@ -31,78 +34,103 @@ } }, content = function() - - ui.field.text{ label = _"Unit", value = initiative.issue.area.unit.name, readonly = true } - ui.field.text{ label = _"Area", value = initiative.issue.area.name, readonly = true } - ui.field.text{ label = _"Policy", value = initiative.issue.policy.name, readonly = true } - ui.field.text{ label = _"Issue", value = _("Issue ##{id}", { id = initiative.issue.id } ), readonly = true } - slot.put("
") - ui.field.text{ label = _"Initiative", value = initiative.name, readonly = true } - + + ui.sectionHead( function() + ui.heading { level = 1, content = initiative.display_name } + end) + if param.get("preview") then - ui.container{ - attr = { class = "draft_content wiki" }, - content = function() - slot.put(format.wiki_text(param.get("content"), param.get("formatting_engine"))) + ui.sectionRow( function() + ui.field.hidden{ name = "formatting_engine", value = param.get("formatting_engine") } + ui.field.hidden{ name = "content", value = param.get("content") } + if config.enforce_formatting_engine then + formatting_engine = config.enforce_formatting_engine + else + formatting_engine = param.get("formatting_engine") end - } - slot.put("
") - ui.submit{ text = _"Save" } - slot.put("
") - slot.put("
") - end - slot.put("
") + ui.container{ + attr = { class = "draft" }, + content = function() + slot.put(format.wiki_text(param.get("content"), formatting_engine)) + end + } + slot.put("
") + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _'Publish now' + }, + content = "" + } + slot.put("
") + slot.put("
") - ui.field.select{ - label = _"Wiki engine", - name = "formatting_engine", - foreign_records = { - { id = "rocketwiki", name = "RocketWiki" }, - { id = "compat", name = _"Traditional wiki syntax" } - }, - attr = {id = "formatting_engine"}, - foreign_id = "id", - foreign_name = "name" - } - ui.tag{ - tag = "div", - content = function() ui.tag{ - tag = "label", - attr = { class = "ui_field_label" }, - content = function() slot.put(" ") end, + tag = "input", + attr = { + type = "submit", + name = "edit", + class = "btn-link", + value = _'Edit again' + }, + content = "" + } + slot.put(" | ") + ui.link{ + content = _"Cancel", + module = "initiative", + view = "show", + id = initiative.id + } + end ) + + else + ui.sectionRow( function() + execute.view{ module = "initiative", view = "_sidebar_wikisyntax" } + + if not config.enforce_formatting_engine then + ui.field.select{ + label = _"Wiki engine", + name = "formatting_engine", + foreign_records = config.formatting_engines, + attr = {id = "formatting_engine"}, + foreign_id = "id", + foreign_name = "name" + } + end + + ui.heading{ level = 2, content = _"Enter your proposal and/or reasons" } + + ui.field.text{ + name = "content", + multiline = true, + attr = { style = "height: 50ex; width: 100%;" }, + value = param.get("content") } ui.tag{ - content = function() - ui.link{ - text = _"Syntax help", - module = "help", - view = "show", - id = "wikisyntax", - attr = {onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} - } - slot.put(" ") - ui.link{ - text = _"(new window)", - module = "help", - view = "show", - id = "wikisyntax", - attr = {target = "_blank", onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} - } - end + tag = "input", + attr = { + type = "submit", + name = "preview", + class = "btn btn-default", + value = _'Preview' + }, + content = "" } - end - } - ui.field.text{ - label = _"Content", - name = "content", - multiline = true, - attr = { style = "height: 50ex;" }, - value = param.get("content") - } - - ui.submit{ name = "preview", text = _"Preview" } - ui.submit{ text = _"Save" } + slot.put("
") + slot.put("
") + + ui.link{ + content = _"Cancel", + module = "initiative", + view = "show", + id = initiative.id + } + + end ) + end end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/draft/show.lua --- a/app/main/draft/show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/draft/show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -2,39 +2,51 @@ local source = param.get("source", atom.boolean) execute.view{ - module = "draft", + module = "issue", view = "_head", - params = { draft = draft} + params = { issue = draft.initiative.issue } } -slot.put_into("title", " · " .. _"History") - -if source then - ui.actions(function() - ui.link{ - content = _"Rendered", - module = "draft", - view = "show", - id = param.get_id(), - params = { source = false } - } - end - ) -else - ui.actions(function() +ui.section( function() + + ui.sectionHead( function() ui.link{ - content = _"Source", - module = "draft", - view = "show", - id = param.get_id(), - params = { source = true } + module = "initiative", view = "show", id = draft.initiative.id, + content = function () + ui.heading { + level = 1, + content = draft.initiative.display_name + } + end } - end - ) -end - -execute.view{ - module = "draft", - view = "_show", - params = { draft = draft, source = source } -} + ui.container { attr = { class = "right" }, content = function() + if source then + ui.link{ + content = _"Rendered", + module = "draft", + view = "show", + id = param.get_id(), + params = { source = false } + } + else + ui.link{ + content = _"Source", + module = "draft", + view = "show", + id = param.get_id(), + params = { source = true } + } + end + end } + ui.heading { level = 2, content = _("Draft revision #{id}", { id = draft.id } ) } + end) + + ui.sectionRow( function() + + execute.view{ + module = "draft", + view = "_show", + params = { draft = draft, source = source } + } + end) +end) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/event/_list.lua --- a/app/main/event/_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ ---local global = param.get("global", atom.boolean) -local for_member = param.get("for_member", "table") -local for_unit = param.get("for_unit", "table") -local for_area = param.get("for_area", "table") -local event_max_id = param.get_all_cgi()["event_max_id"] -local event_selector = Event:new_selector() - :add_order_by("event.id DESC") - :limit(25) - :join("issue", nil, "issue.id = event.issue_id") - :add_field("now()::date - event.occurrence::date", "time_ago") - -if event_max_id then - event_selector:add_where{ "event.id < ?", event_max_id } -end - -if for_member then - event_selector:add_where{ "event.member_id = ?", for_member.id } -elseif for_unit then - event_selector:join("area", nil, "area.id = issue.area_id") - event_selector:add_where{ "area.unit_id = ?", for_unit.id } -elseif for_area then - event_selector:add_where{ "issue.area_id = ?", for_area.id } ---elseif not global then --- event_selector:join("event_seen_by_member", nil, { "event_seen_by_member.id = event.id AND event_seen_by_member.seen_by_member_id = ?", app.session.member_id }) -end - -if app.session.member_id then - event_selector - :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id } ) - :add_field("(_interest.member_id NOTNULL)", "is_interested") - :left_join("delegating_interest_snapshot", "_delegating_interest", { "_delegating_interest.issue_id = issue.id AND _delegating_interest.member_id = ? AND _delegating_interest.event = issue.latest_snapshot_event", app.session.member.id } ) - :add_field("_delegating_interest.delegate_member_ids[1]", "is_interested_by_delegation_to_member_id") - :add_field("_delegating_interest.delegate_member_ids[array_upper(_delegating_interest.delegate_member_ids, 1)]", "is_interested_via_member_id") - :add_field("array_length(_delegating_interest.delegate_member_ids, 1)", "delegation_chain_length") -end - -local filters = execute.load_chunk{module="issue", chunk="_filters.lua", params = { - for_events = true, - member = app.session.member, for_member = for_member, state = for_state, for_unit = for_unit and true or false, for_area = for_area and true or false -}} - -filters.opened = true -filters.selector = event_selector - -filters.content = function() - - - local last_event_id - - local events = event_selector:exec() - - local issues = events:load("issue") - issues:load_everything_for_member_id(app.session.member_id) - - events:load("initiative") - events:load("suggestion") - events:load("member") - - - ui.container{ attr = { class = "issues events" }, content = function() - - local last_event_date - for i, event in ipairs(events) do - last_event_id = event.id - - ui.container{ attr = { class = "event_info" }, content = function() - local event_name = event.event_name - local event_image - if event.event == "issue_state_changed" then - if event.state == "discussion" then - event_name = _"Discussion started" - event_image = "comments.png" - elseif event.state == "verification" then - event_name = _"Verification started" - event_image = "lock.png" - elseif event.state == "voting" then - event_name = _"Voting started" - event_image = "email_open.png" - elseif event.state == "finished_with_winner" then - event_name = event.state_name - event_image = "award_star_gold_2.png" - elseif event.state == "finished_without_winner" then - event_name = event.state_name - event_image = "cross.png" - else - event_name = event.state_name - end - if event_image then - ui.image{ static = "icons/16/" .. event_image } - slot.put(" ") - end - end - local days_ago_text - if event.time_ago == 0 then - days_ago_text = _("Today at #{time}", { time = format.time(event.occurrence) }) - elseif event.time_ago == 1 then - days_ago_text = _("Yesterday at #{time}", { time = format.time(event.occurrence) }) - else - days_ago_text = _("#{date} at #{time}", { date = format.date(event.occurrence.date), time = format.time(event.occurrence, { hide_seconds = true }) }) - end - ui.tag{ attr = { class = "event_name" }, content = event_name } - slot.put("
") - ui.tag{ content = days_ago_text } - --[[ if event.time_ago > 1 then - slot.put("
(") - ui.tag{ content = _("#{count} days ago", { count = event.time_ago }) } - slot.put(")") - end - --]] - if app.session:has_access("authors_pseudonymous") and event.member_id then - slot.put("
") - slot.put("
") - if app.session.member_id then - ui.link{ - content = function() - execute.view{ - module = "member_image", - view = "_show", - params = { - member = event.member, - image_type = "avatar", - show_dummy = true, - class = "micro_avatar", - popup_text = text - } - } - end, - module = "member", view = "show", id = event.member_id - } - slot.put(" ") - end - ui.link{ - text = event.member.name, - module = "member", view = "show", id = event.member_id - } - end - end } - - ui.container{ attr = { class = "issue" }, content = function() - - execute.view{ module = "delegation", view = "_info", params = { issue = event.issue, member = for_member } } - - ui.container{ attr = { class = "content" }, content = function() - ui.link{ - module = "unit", view = "show", id = event.issue.area.unit_id, - attr = { class = "unit_link" }, text = event.issue.area.unit.name - } - slot.put(" ") - ui.link{ - module = "area", view = "show", id = event.issue.area_id, - attr = { class = "area_link" }, text = event.issue.area.name - } - end } - - ui.container{ attr = { class = "title" }, content = function() - ui.link{ - attr = { class = "issue_id" }, - text = _("#{policy} ##{id}", { policy = event.issue.policy.name, id = event.issue_id }), - module = "issue", - view = "show", - id = event.issue_id - } - end } - - ui.container{ attr = { class = "initiative_list" }, content = function() - if not event.initiative_id then - local initiatives_selector = Initiative:new_selector() - :add_where{ "initiative.issue_id = ?", event.issue_id } - :add_order_by("initiative.admitted DESC NULLS LAST, initiative.rank NULLS LAST, initiative.harmonic_weight DESC NULLS LAST, id") - execute.view{ module = "initiative", view = "_list", params = { - issue = event.issue, - initiatives_selector = initiatives_selector, - no_sort = true, - limit = 5, - for_member = for_member - } } - else - local initiatives_selector = Initiative:new_selector() - :add_where{ "initiative.id = ?", event.initiative_id } - execute.view{ module = "initiative", view = "_list", params = { - initiatives_selector = initiatives_selector, - no_sort = true, - hide_more_initiatives = true, - for_member = for_member - } } - end - end } - - ui.container{ attr = { class = "content suggestion" }, content = function() - if event.suggestion_id then - ui.link{ - text = event.suggestion.name, - module = "suggestion", view = "show", id = event.suggestion_id - } - end - end } - end } - end - - end } - - slot.put("
") - - if #events > 0 then - ui.link{ - attr = { class = "more_events_links" }, - text = _"Show older events", - module = request.get_module(), - view = request.get_view(), - id = for_unit and for_unit.id or for_area and for_area.id, - params = { - tab = param.get_all_cgi()["tab"], - events = param.get_all_cgi()["events"], - event_max_id = last_event_id - } - } - else - ui.tag{ content = _"No more events available" } - end - - slot.put("
") - slot.put("
") - -end - - -ui.filters(filters) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/help/introduction.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/help/introduction.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,132 @@ +ui.title(_"Introduction") + +local lang = locale.get("lang") + +ui.section(function() + ui.sectionHead(function() + ui.heading{ level = 1, content = _"Structured discussion" } + end) + ui.sectionRow(function() + ui.heading{ level = 2, content = _"Initiatives and issues" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + LiquidFeedback ist kein Umfragesystem, es werden keine bereits vorher feststehenden Fragen gestellt. Statt dessen kann jeder Teilnehmer neue Initiativen starten, die Vorschläge und/oder Argumente umfassen. Sobald eine Initiative eingestellt wurde, können alle Teilnehmer alternative Initiativen mit Gegenvorschlägen starten. Alle zueinander in Konkrurrenz stehenden Initiativen bilden zusammen ein Thema. Sowohl Themen als auch Initiativen werden nummeriert. Themen erhalten hierbei vor der Nummer ein #-Zeichen (z. B. #123), während Initiativen durch ein führendes i gekennzeichnet sind (z. B. i456). Ein Thema kann mehrere Initiativen enthalten. Nur eine Initiative kann gewinnen. + ]] } + else + ui.tag{ tag = "p", content = [[ + LiquidFeedback is no survey, it doesn't ask you predefined questions. Instead every participant is allowed to post new initiatives containing a proposal and/or reasoning. As soon as the initiative is posted, all other participants can create alternative initiatives with counter proposals and/or reasoning. A group of concurring initiatives forms an issue. Issues in LiquidFeedback are numbered with a hash sign (e.g. #123) while initiatives are numbered with a leading "i" character (i456). In short: One issue may contain multiple initiatives. Only one initiative can win. + ]] } + end + + ui.heading{ level = 2, content = _"Subject areas" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Themen werden immer einem Themenbereich zugeordnet. Dies dient der Strukturierung der Diskussion und des Entscheidungsprozesses. + ]] } + else + ui.tag{ tag = "p", content = [[ + Issues are always assigned to a subject area in order to structure the discussion and decision process. + ]] } + end + ui.heading{ level = 2, content = _"Organizational units" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Gliederungen ermöglichen Diskussionen und Entscheidungen auch für Teilmengen der Benutzer (z. B. Gliederungen einer Organisation). In jeder Gliederung können eigene Themenbereiche zur Verfügung stehen. + ]] } + else + ui.tag{ tag = "p", content = [[ + To allow discussions and decisions by sub groups of participants (e.g. by the members of a subdivision of an organization), participants can be assigned to different units. Every organizational unit can have its own subject areas. + ]] } + end + ui.heading{ level = 2, content = _"Rules of procedure" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Ein Regelwerk definiert Fristen, Quoren und erforderliche Mehrheiten. Initiatoren wählen bei Erstellung eines Themas ein geeignetes Verfahren, das dem verfolgten Zweck entspricht. + ]] } + else + ui.tag{ tag = "p", content = [[ + A policy defines the timing, quorums and required majorities for an issue in LiquidFeedback. Initiators choose the fitting policy for their purpose when creating a new issue. + ]] } + end + end ) +end ) +ui.section(function() + ui.sectionHead(function() + ui.heading{ level = 1, content = _"4 phases of a decision" } + end) + ui.sectionRow(function() + ui.heading{ level = 2, content = _"(1) Admission phase" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Nicht jedes neue Thema wird auf ein Mindestinteresse der Teilnehmer stoßen. Daher muss ein neues Thema von einer vorab festzulegenden Mindestanzahl Teilnehmer als diskussionswürdig betrachtet werden, um für die Diskussionsphase zugelassen zu werden. Andernfalls wird das Thema am Ende der Zulassungsphase abgebrochen und nicht weiter behandelt. + ]] } + else + ui.tag{ tag = "p", content = [[ + As every participant can open a new issue in LiquidFeedback, not all of them will be intersting for at least a minimum of the participants. Therefore new issues need to gain a given quorum of supporters to become accepted for further discussion. Issues which do not reach the necessary quorum will be closed at the end of the admission phase. + ]] } + end + ui.heading{ level = 2, content = _"(2) Discussion phase" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Während der Diskussionsphase arbeiten Initiativen auf die Verbesserung des Vorschlags und die Vervollkommnung der Argumentation hin, um die erforderliche Mehrheit zu erreichen und sich gegen eventuell vorhandene alternative Initiativen durchzusetzen. + ]] } + else + ui.tag{ tag = "p", content = [[ + During the discussion phase all initiatives try to improve their proposals and reasoning to gain more supporters. The aim is to eventually reach the necessary majority and to beat alternative initiatives. + ]] } + end + ui.heading{ level = 2, content = _"(3) Verification phase" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Alle in dieser Phase angezeigten Initiativtexte können nicht mehr verändert werden. Neue Initiativen können gestartet aber ebenfalls nicht mehr geändert werden. Dieses Vorgehen schützt die Teilnehmer vor überraschenden Änderungen in letzter Minute. + ]] } + else + ui.tag{ tag = "p", content = [[ + During the verification phase, initiative drafts with the proposal and reasoning become final and cannot be changed any more. So everyone can double check everything. In case of some last minute situation, it is still possible to add competing initiatives. But they cannot be edited again and need to gain supporters from scratch. + ]] } + end + ui.heading{ level = 2, content = _"(4) Voting phase" } + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Jede Initiative, die eine Mindestanzahl an Unterstützern erreicht, wird zur Abstimmung zugelassen und erscheint auf dem Stimmzettel. Während der Abstimmung können die Teilnehmer mittels Präferenzwahl abstimmen, die es neben Zustimmung, Enthaltung und Ablehnung zusätzlich erlaubt Präferenzen zwischen den Initiativen anzugeben. + ]] } + else + ui.tag{ tag = "p", content = [[ + Every initiative reaching a required quorum of supporters at the end of the verification phase is admitted for voting and appears on the voting ballot. During the voting phase every eligible participant may give a vote using a preferential voting system allowing to express individual preferences between the initiatives in addition to a yes/neutral/no vote. + ]] } + end + + end) +end) +ui.section(function() + ui.sectionHead(function() + ui.heading{ level = 1, content = _"Vote delegation" } + end) + ui.sectionRow(function() + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Delegationen ermöglichen eine dynamische Arbeitsteilung. Sie entsprechen einer Stimmrechtsvollmacht, können jederzeit geändert werden, sind weisungsfrei und übertragbar. Delegationen können für eine Gliederung, für einen Themenbereich der Gliederung oder für ein konkretes Thema erteilt werden. Konkretere Delegationen gehen allgemeineren Delegationen vor. Delegationen werden sowohl für den Diskurs (Phasen 1 bis 3) als auch für die Abstimmphase genutzt. Bei Aktivität eines Benutzers werden eventuell vorhandene Delegationen für die jeweilige Aktivität ausgesetzt. + ]] } + else + ui.tag{ tag = "p", content = [[ + Delegations allow for a dynamic division of labor. A delegation is a proxy statement (voting power under a power of attorney), can be altered at any time, is not bound to directives and can be delegated onward. Delegations can be used for a whole organizational unit, for a subject area within an organizational unit, or for a specific issue. More specific delegations overrule more general delegations. Delegations are used in both the discourse (phase 1 to 3) and the voting phase. Any activity suspends existing delegations for the given activity. + ]] } + end + end) +end) +ui.section(function() + ui.sectionHead(function() + ui.heading{ level = 1, content = _"Preference voting" } + end) + ui.sectionRow(function() + if lang == "de" then + ui.tag{ tag = "p", content = [[ + Im Falle mehrerer ähnlicher Vorschläge auf dem Stimmzettel gibt es keine Notwendigkeit einen dieser Vorschläge auszuwählen. Stattdessen kann für (bzw. gegen) beliebig viele konkurrierende Initiativen gestimmt werden und gleichzeitig eine Präferenzreihenfolge dieser Initiativen angegeben werden. Die Präferenzen bestimmen den Gewinner, falls am Ende mehr als eine Initiative die notwendige Mehrheit an Ja-Stimmen erreicht. Auf diese Weise wird niemand ermutigt für eine Initiative zu stimmen, nur um eine andere Initiative zu verhindern, und es wird niemand ermutigt gegen eine Initiative zu stimmen, nur um einer anderen Initiative eine Chance zu geben. + ]] } + else + ui.tag{ tag = "p", content = [[ + If there are similar competing proposals on the ballot, there is no necessity to choose one of them. Instead, it is possible to vote for (and against) as many initiatives as one wants to while being able to express the individual preferences amongst those initiatives during voting phase. Those preferences will determine the winner if more than one initiative has reached the necessary majority of approvals at end of voting phase. That way, nobody is encouraged to vote in favor of one initiative just to outrank another one, and nobody is encouraged to vote against an initiative just to increase the chances for another initiative to win. + ]] } + end + end) +end) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/404.lua --- a/app/main/index/404.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/404.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,3 +1,13 @@ ui.title("404 Not found") -ui.container{ content = "Page not found" } +ui.section(function() + ui.sectionHead(function() + ui.heading{ level = 1, content = _"Page not found" } + end) + ui.sectionRow(function() + ui.link{ + content = _"Go back to home page", + module = "index", view = "index" + } + end) +end) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_action/login.lua --- a/app/main/index/_action/login.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/_action/login.lua Thu Jul 10 01:19:48 2014 +0200 @@ -90,6 +90,18 @@ if config.etherpad then do_etherpad_auth(member) end + slot.select("script", function() + ui.script{ script = [[ + $('#swiper_info').addClass('active'); + ]] } + end) + slot.select("swiper_info", function() + ui.tag { content = _"select tabs" } + slot.put(" ↑ ") + ui.tag { content = _"or swipe" } + slot.put(" ←
") + ui.tag { content = _"to show more info and learn what you can do" } + end ) else slot.select("error", function() ui.tag{ content = _'Invalid login name or password!' } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_login.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_login.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,37 @@ +ui.form{ + attr = { class = "login" }, + module = 'index', + action = 'login', + routing = { + ok = { + mode = 'redirect', + module = param.get("redirect_module") or "index", + view = param.get("redirect_view") or "index", + id = param.get("redirect_id"), + }, + error = { + mode = 'forward', + module = 'index', + view = 'login', + } + }, + content = function() + ui.field.text{ + attr = { id = "username_field" }, + label = _'login name', + 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' + } + slot.put("  ") + ui.link{ module = "index", view = "reset_password", text = _"Forgot password?" } + end +} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_motd.lua --- a/app/main/index/_motd.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -if config.motd_intern then - local help_text = config.motd_intern - ui.container{ - attr = { class = "wiki" }, - content = function() - slot.put(format.wiki_text(help_text)) - end - } -end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_sidebar_members.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_sidebar_members.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,33 @@ +if not app.session:has_access("all_pseudonymous") then + return +end + +ui.sidebar ( "tab-members", function () + local member_count = MemberCount:get() + ui.sidebarHead( function() + ui.heading { + level = 2, + content = _("Registered members (#{count})", { count = member_count }) + } + end ) + + local selector = Member:new_selector() + :add_where("active") + :add_order_by("last_login DESC NULLS LAST, id DESC") + :limit(50) + + execute.view { + module = 'member', view = '_list', params = { + members_selector = selector, + no_filter = true, no_paginate = true, + member_class = "sidebarRow sidebarRowNarrow" + } + } + + ui.link { + attr = { class = "sidebarRow moreLink" }, + text = _"Show full member list", + module = "member", view = "list" + } + +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_sidebar_motd_intern.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_sidebar_motd_intern.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,10 @@ +if config.motd_intern then + slot.select("motd", function() + ui.container{ + attr = { class = "wiki motd" }, + content = function() + slot.put(config.motd_intern) + end + } + end ) +end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_sidebar_motd_public.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_sidebar_motd_public.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,10 @@ +if config.motd_public then + slot.select("motd", function() + ui.container{ + attr = { class = "wiki motd" }, + content = function() + slot.put(config.motd_public) + end + } + end ) +end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_sidebar_notifications.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_sidebar_notifications.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,132 @@ +local notification_links = {} + +if app.session.member.notify_email_unconfirmed then + notification_links[#notification_links+1] = { + module = "index", view = "email_unconfirmed", + text = _"Confirm your email address" + } +end + +if app.session.member.notify_level == nil then + notification_links[#notification_links+1] = { + module = "member", view = "settings_notification", + text = _"Select a notification level" + } +end + +if config.check_delegations_interval_soft then + local member = Member:new_selector() + :add_where({ "id = ?", app.session.member_id }) + :add_field({ "now() > COALESCE(last_delegation_check, activated) + ?::interval", config.check_delegations_interval_soft }, "needs_delegation_check_soft") + :single_object_mode() + :exec() + + + if member.needs_delegation_check_soft then + + local delegations = Delegation:delegations_to_check_for_member_id(member.id) + + if #delegations > 0 then + notification_links[#notification_links+1] = { + module = "index", view = "check_delegations", + text = _"Check your outgoing delegations" + } + end + + end +end + +local broken_delegations = Delegation:selector_for_broken(app.session.member_id):exec() + +for i, delegation in ipairs(broken_delegations) do + local scope + local context + if delegation.scope == "unit" then + scope = _"unit" + id = delegation.unit_id + context = delegation.unit.name + elseif delegation.scope == "area" then + scope = _"area" + id = delegation.area_id + context = delegation.area.name + elseif delegation.scope == "issue" then + scope = _"issue" + id = delegation.issue_id + context = delegation.issue.name + end + + notification_links[#notification_links+1] = { + module = delegation.scope, view = "show", id = id, + text = _("Check your #{scope} delegation to '#{trustee_name}' for '#{context}'", { + trustee_name = delegation.trustee.name, + scope = scope, + context = context + }) + } +end + +local selector = Issue:new_selector() + :join("area", nil, "area.id = issue.area_id") + :join("privilege", nil, { "privilege.unit_id = area.unit_id AND privilege.member_id = ? AND privilege.voting_right", app.session.member_id }) + :left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id }) + :left_join("non_voter", nil, { "non_voter.issue_id = issue.id AND non_voter.member_id = ?", app.session.member.id }) + :left_join("interest", nil, { "interest.issue_id = issue.id AND interest.member_id = ?", app.session.member.id }) + :add_where{ "direct_voter.member_id ISNULL" } + :add_where{ "non_voter.member_id ISNULL" } + :add_where{ "interest.member_id NOTNULL" } + :add_where{ "issue.fully_frozen NOTNULL" } + :add_where{ "issue.closed ISNULL" } + :add_order_by{ "issue.fully_frozen + issue.voting_time ASC" } + +local issues_to_vote = selector:exec() + +for i, issue in ipairs(issues_to_vote) do + notification_links[#notification_links+1] = { + module = "issue", view = "show", id = issue.id, + text = _("#{issue} is in voting", { issue = issue.name }) + } +end + +local initiator_invites = Initiator:selector_for_invites(app.session.member_id):exec() + +for i, initiative in ipairs(initiator_invites) do + notification_links[#notification_links+1] = { + module = "initiative", view = "show", id = initiative.id, + text = _("You are invited to become initiator of '#{initiative_name}'", { initiative_name = initiative.display_name }) + } +end + +updated_drafts = Initiative:selector_for_updated_drafts(app.session.member_id):exec() + +for i, initiative in ipairs(updated_drafts) do + notification_links[#notification_links+1] = { + module = "initiative", view = "show", id = initiative.id, + text = _("New draft for initiative '#{initiative_name}'", { initiative_name = initiative.display_name }) + } +end + +local mode = param.get("mode") or "view" + +if #notification_links > 0 then + if mode == "link" then + slot.select("notification", function () + local text = _"notifications" + ui.link { + attr = { class = "notifications", title = text }, + module = "index", view = "notifications", + content = function () + ui.image { attr = { class = "icon", alt = text }, static = "icons/48/bell.png" } + ui.tag { attr = { class = "count" }, content = #notification_links } + end + } + end ) + elseif mode == "view" then + ui.tag{ tag = "ul", attr = { class = "ul" }, content = function() + for i, notification_link in ipairs(notification_links) do + ui.tag{ tag = "li", content = function() + ui.link(notification_link) + end } + end + end } + end +end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_sidebar_units.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_sidebar_units.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,154 @@ +local member = param.get ( "member", "table" ) +local units +if member then + units = member.units + units:load_delegation_info_once_for_member_id(member.id) +else + units = Unit:new_selector():add_where("active"):add_order_by("name"):exec() + ui.sidebar( "tab-whatcanido", function() + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Organizational units" } + end ) + ui.sidebarSection( function() + execute.view { module = "unit", view = "_list" } + end ) + end ) + return +end + + +for i, unit in ipairs(units) do + + ui.sidebar ( "tab-whatcanido units", function () + + local areas_selector = Area:new_selector() + :reset_fields() + :add_field("area.id", nil, { "grouped" }) + :add_field("area.unit_id", nil, { "grouped" }) + :add_field("area.name", nil, { "grouped" }) + :add_where{ "area.unit_id = ?", unit.id } + :add_where{ "area.active" } + :add_order_by("area.name") + + if member then + areas_selector:left_join ( + "membership", nil, + { "membership.area_id = area.id AND membership.member_id = ?", member.id } + ) + areas_selector:add_field("membership.member_id NOTNULL", "subscribed", { "grouped" }) + end + + local areas = areas_selector:exec() + if member then + areas:load_delegation_info_once_for_member_id(member.id) + end + + if #areas > 0 then + + ui.container { + attr = { class = "sidebarHead" }, + content = function () + ui.heading { level = 2, content = function () + ui.link { + attr = { class = "unit" }, + module = "unit", view = "show", id = unit.id, + content = unit.name + } + + if member then + local delegation = Delegation:by_pk(member.id, unit.id, nil, nil) + + if delegation then + ui.link { + module = "delegation", view = "show", params = { + unit_id = unit.id + }, + attr = { class = "delegation_info" }, + content = function () + ui.delegation(delegation.trustee_id, delegation.trustee.name) + end + } + end + end + end } + + end + } + + + ui.tag { tag = "div", attr = { class = "areas areas-" .. unit.id }, content = function () + + local any_subscribed = false + local subscribed_count = 0 + for i, area in ipairs(areas) do + + local class = "sidebarRow" + class = class .. (not area.subscribed and " disabled" or "") + + ui.tag { tag = "div", attr = { class = class }, content = function () + + if area.subscribed then + local text = _"subscribed" + ui.image { attr = { class = "icon24 star", alt = text, title = text }, static = "icons/48/star.png" } + any_subscribed = true + subscribed_count = subscribed_count +1 + end + + if member then + local delegation = Delegation:by_pk(member.id, nil, area.id, nil) + + if delegation then + ui.link { + module = "delegation", view = "show", params = { + area_id = area.id + }, + attr = { class = "delegation_info" }, + content = function () + ui.delegation(delegation.trustee_id, delegation.trustee_id and delegation.trustee.name) + end + } + end + end + + slot.put ( " " ) + + ui.link { + attr = { class = "area" }, + module = "area", view = "show", id = area.id, + content = area.name + } + + + end } + end + if subscribed_count < #areas then + local text + if any_subscribed then + text = _"show other subject areas" + else + text = _"show subject areas" + end + ui.script{ script = "$('.areas-" .. unit.id .. "').addClass('folded');" } + ui.tag { tag = "div", attr = { class = "sidebarRow moreLink whenfolded" }, content = function () + ui.link { + attr = { + onclick = "$('.areas-" .. unit.id .. "').removeClass('folded'); return false;" + }, + text = text + } + end } + ui.tag { tag = "div", attr = { class = "sidebarRow moreLink whenunfolded" }, content = function () + ui.link { + attr = { + onclick = "$('.areas-" .. unit.id .. "').addClass('folded'); return false;" + }, + text = _"collapse subject areas" + } + end } + end + end } + end + end ) +end + + diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/_sidebar_whatcanido.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_sidebar_whatcanido.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,71 @@ +ui.sidebar ( "tab-whatcanido", function () + + ui.sidebarHeadWhatCanIDo() + + if app.session.member then + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to know whats going on" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = _"take a look on the issues (see left)" } + ui.tag { tag = "li", content = _"by default only those issues are shown, for which your are eligible to participate (change filters on top of the list)" } + end } + end ) + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to stay informed" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag{ content = _"check your " } + ui.link{ + module = "member", view = "settings_notification", + params = { return_to = "home" }, + text = _"notifications settings" + } + end } + ui.tag { tag = "li", content = function () + ui.tag{ content = _"subscribe subject areas or add your interested to issues and you will be notified about changes (follow the instruction on the area or issue page)" } + end } + end } + end ) + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to start a new initiative" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." } + end } + end ) + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to delegate my vote" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = _"open the organizational unit, subject area or issue you like to delegate and follow the instruction on that page." } + end } + end ) + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to take a look at other organizational units" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + module = "unit", view = "list", + text = _"show all units" + } + end } + end } + end ) + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to learn more about LiquidFeedback" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function() + ui.link { module = "help", view = "introduction", content = _"structured discussion" } + end } + ui.tag { tag = "li", content = function() + ui.link { module = "help", view = "introduction", content = _"4 phases of a decision" } + end } + ui.tag { tag = "li", content = function() + ui.link { module = "help", view = "introduction", content = _"vote delegation" } + end } + ui.tag { tag = "li", content = function() + ui.link { module = "help", view = "introduction", content = _"preference voting" } + end } + end } + end ) + end + +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/about.lua --- a/app/main/index/about.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/about.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,102 +1,91 @@ ui.title(_"About site") -if app.session.member_id and config.use_terms then - ui.actions(function() - ui.link{ - module = "index", - view = "usage_terms", - text = _"Terms of use" - } - end) -end +ui.section( function() + ui.sectionHead( function() + ui.heading{ level = 1, content = _"About site" } + end ) + + ui.sectionRow( function() -slot.put("
") -ui.field.text{ attr = { style = "font-weight: bold;" }, value = _"This service is provided by:" } -slot.put("
") - -slot.put(config.app_service_provider) + ui.heading{ level = 3, content = _"This service is provided by:" } + slot.put(config.app_service_provider) -slot.put("
") -slot.put("
") -slot.put("
") + end ) + ui.sectionRow( function() -ui.field.text{ attr = { style = "font-weight: bold;" }, value = _"This service is provided using the following software components:" } -slot.put("
") + ui.heading{ level = 3, content = _"This service is provided using the following software components:" } -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" - }, -} + 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 + ui.list{ + records = tmp, + columns = { + { + content = function(record) + ui.link{ + content = record.name, + external = record.url + } + end + }, + { + content = function(record) ui.field.text{ value = record.version } end + }, + { + content = function(record) + ui.link{ + content = record.license, + external = record.license_url + } + end + } - 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 + } + } + + end ) - } - } -} + ui.sectionRow( function() + ui.heading{ level = 3, content = "3rd party license information:" } + slot.put('Some of the icons used in Liquid Feedback are from Silk icon set 1.3 by Mark James. His work is licensed under a Creative Commons Attribution 2.5 License.') -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.') - + end ) +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/check_delegations.lua --- a/app/main/index/check_delegations.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/check_delegations.lua Thu Jul 10 01:19:48 2014 +0200 @@ -8,12 +8,6 @@ end end) -if app.session.needs_delegation_check then - util.help("index.check_delegations_hard", _"Check delegations") -else - util.help("index.check_delegations", _"Check delegations") -end - ui.form{ module = "index", action = "check_delegations", routing = { diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/document.lua --- a/app/main/index/document.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/document.lua Thu Jul 10 01:19:48 2014 +0200 @@ -15,8 +15,6 @@ } end) -util.help("index.document", _"Download documents") - local file_list = extos.listdir(config.document_dir) local tmp = {} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/download.lua --- a/app/main/index/download.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/download.lua Thu Jul 10 01:19:48 2014 +0200 @@ -15,12 +15,10 @@ } end) -util.help("index.download", _"Download") - ui.container{ attr = { class = "wiki use_terms" }, content = function() - slot.put(format.wiki_text(config.download_use_terms)) + slot.put(config.download_use_terms) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/email_unconfirmed.lua --- a/app/main/index/email_unconfirmed.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/email_unconfirmed.lua Thu Jul 10 01:19:48 2014 +0200 @@ -7,48 +7,50 @@ :optional_object_mode() :exec() - slot.select("head", function() - ui.container{ - attr = { class = "title" }, - content = _"Notification address unconfirmed" - } - end ) + ui.title(_"Confirm notification address") - if current then - ui.tag{ - tag = "div", - content = _("You didn't confirm your email address '#{email}'. You have received an email with an activation link.", { email = app.session.member.notify_email_unconfirmed }) - } - else - ui.tag{ - tag = "div", - content = _("You didn't confirm your email address '#{email}' within 7 days.", { email = app.session.member.notify_email_unconfirmed }) - } - end - slot.put("
") + ui.section( function() + ui.sectionHead( function() + ui.heading{ level = 1, content = _"Notification address unconfirmed" } + end ) + + ui.sectionRow( function() + if current then + ui.tag{ + tag = "div", + content = _("You didn't confirm your email address '#{email}'. You have received an email with an activation link.", { email = app.session.member.notify_email_unconfirmed }) + } + else + ui.tag{ + tag = "div", + content = _("You didn't confirm your email address '#{email}' within 7 days.", { email = app.session.member.notify_email_unconfirmed }) + } + end + slot.put("
") - ui.link{ - text = _"Change email address", - module = "member", - view = "settings_email", - } - slot.put("
") - slot.put("
") + ui.link{ + text = _"Change email address", + module = "member", + view = "settings_email", + } + slot.put("
") + slot.put("
") - ui.link{ - text = _("Resend activation email to '#{email}'", { email = app.session.member.notify_email_unconfirmed }), - module = "member", - action = "update_email", - params = { - resend = true - }, - routing = { - default = { - mode = "redirect", - module = "index", - view = "index" + ui.link{ + text = _("Resend activation email to '#{email}'", { email = app.session.member.notify_email_unconfirmed }), + module = "member", + action = "update_email", + params = { + resend = true + }, + routing = { + default = { + mode = "redirect", + module = "index", + view = "index" + } + } } - } - } - + end ) + end ) end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/index.lua --- a/app/main/index/index.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/index.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,132 +1,114 @@ -if app.session.member_id then - util.help("index.index", _"Home") +function getIssuesSelector() + return Issue:new_selector() + :add_order_by([[ + coalesce( + issue.fully_frozen + issue.voting_time, + issue.half_frozen + issue.verification_time, + issue.accepted + issue.discussion_time, + issue.created + issue.admission_time + ) - now() + ]]) +end - execute.view{ - module = "index", view = "_index_member" - } +--[[ +ui.title( function () + ui.link { attr = { class = "home" }, module = "index", view = "index", text = _"Home" } +end) +--]] + +ui.title() -elseif app.session:has_access("anonymous") then - if config.motd_public then - local help_text = config.motd_public - ui.container{ - attr = { class = "wiki motd" }, - content = function() - slot.put(format.wiki_text(help_text)) - end - } - end +if false then +slot.select ( "tabs", function () - local open_issues_selector = Issue:new_selector() - :add_where("issue.closed ISNULL") - :add_order_by("coalesce(issue.fully_frozen + issue.voting_time, issue.half_frozen + issue.verification_time, issue.accepted + issue.discussion_time, issue.created + issue.admission_time) - now()") - - local closed_issues_selector = Issue:new_selector() - :add_where("issue.closed NOTNULL") - :add_order_by("issue.closed DESC") - + ui.tag { + attr = { onclick = "showTab(0);" }, + content = "units", + } + slot.put ( " " ) + ui.tag { + attr = { onclick = "showTab(1);" }, + content = "timeline" + } + slot.put ( " " ) + ui.tag { + attr = { onclick = "showTab(2);" }, + content = "what" + } + slot.put ( " " ) + ui.tag { + attr = { onclick = "showTab(3);" }, + content = "members" + } - local tabs = { - module = "index", - view = "index" - } - - tabs[#tabs+1] = { - name = "units", - label = _"Units", - module = "unit", - view = "_list" - } +end ) - tabs[#tabs+1] = { - name = "timeline", - label = _"Latest events", - module = "event", - view = "_list", - params = { global = true } - } +ui.script { script = [[ + + var tabs = ["tab1", "main", "tab2", "tab3"] + var currentId; + + function showTab(id) { + var tabId = tabs[id]; + $('.tab').hide(); + $('.main').hide(); + $('.' + tabId).show(); + currentId = id; + }; + + showTab(0); + + $(function(){ + // Bind the swipeHandler callback function to the swipe event on div.box + $( "body" ).on( "swiperight", function swipeHandler( event ) { + newId = currentId - 1; + if (newId < 0) return; + showTab(newId); + } ) + $( "body" ).on( "swipeleft", function swipeHandler( event ) { + newId = currentId + 1; + if (newId > tabs.length - 1) return; + showTab(newId); + } ) + }); + +]]} +end - tabs[#tabs+1] = { - name = "open", - label = _"Open issues", - module = "issue", - view = "_list", - params = { - for_state = "open", - issues_selector = open_issues_selector + +if app.session.member then + execute.view{ module = "index", view = "_sidebar_motd_intern" } +else + execute.view{ module = "index", view = "_sidebar_motd_public" } +end + +if app.session:has_access("anonymous") then + -- show the units the member has voting privileges for + execute.view { + module = "index", view = "_sidebar_units", params = { + member = app.session.member } } - tabs[#tabs+1] = { - name = "closed", - label = _"Closed issues", - module = "issue", - view = "_list", - params = { - for_state = "closed", - issues_selector = closed_issues_selector - } - } - - if app.session:has_access('all_pseudonymous') then - tabs[#tabs+1] = { - name = "members", - label = _"Members", - module = 'member', - view = '_list', - params = { members_selector = Member:new_selector():add_where("active") } - } - end - - ui.tabs(tabs) - -else - - if config.motd_public then - local help_text = config.motd_public - ui.container{ - attr = { class = "wiki motd" }, - content = function() - slot.put(format.wiki_text(help_text)) - end - } - end - - ui.tag{ tag = "p", content = _"Closed user group, please login to participate." } +end - ui.form{ - attr = { class = "login" }, - module = 'index', - action = 'login', - routing = { - ok = { - mode = 'redirect', - module = param.get("redirect_module") or "index", - view = param.get("redirect_view") or "index", - id = param.get("redirect_id"), - }, - error = { - mode = 'forward', - module = 'index', - view = 'login', - } - }, - content = function() - ui.field.text{ - attr = { id = "username_field" }, - label = _'login name', - 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 -} +-- show the user what can be done +execute.view { module = "index", view = "_sidebar_whatcanido" } +-- show active members +if app.session:has_access("all_pseudonymous") then + execute.view{ module = "index", view = "_sidebar_members" } end +if app.session:has_access("anonymous") then + + if not app.session.member then +-- execute.view { +-- module = "slideshow", view = "_index" +-- } + end + + execute.view { + module = "issue", view = "_list2", params = { } + } + +end -- if app.session:has_access "anonymous" \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/login.lua --- a/app/main/index/login.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/login.lua Thu Jul 10 01:19:48 2014 +0200 @@ -5,32 +5,47 @@ end } -ui.actions() - ui.title(_"Login") app.html_title.title = _"Login" -if config.motd_public then - local help_text = config.motd_public - ui.container{ - attr = { class = "wiki motd" }, - content = function() - slot.put(format.wiki_text(help_text)) - end - } -end +execute.view{ module = "index", view = "_sidebar_motd_public" } + +ui.section(function() + +ui.sectionHead(function() + ui.heading{ level = 1, content = _"Login" } + ui.container { attr = { class = "right" }, content = function() + for i, lang in ipairs(config.enabled_languages) do -if app.session:has_access("anonymous") then - ui.tag{ - tag = 'p', - content = _'You need to be logged in, to use all features of this system.' - } -else - ui.tag{ tag = "p", content = _"Closed user group, please login to participate." } -end - + locale.do_with({ lang = lang }, function() + langcode = _("[Name of Language]") + end) + + if i > 1 then + slot.put(" | ") + end + + ui.link{ + content = function() + ui.tag{ content = langcode } + 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) ui.form{ - attr = { class = "login" }, module = 'index', action = 'login', routing = { @@ -47,22 +62,36 @@ } }, content = function() - ui.field.text{ - attr = { id = "username_field" }, - label = _'login name', - 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' - } - slot.put("  ") - ui.link{ module = "index", view = "reset_password", text = _"Forgot password?" } + ui.sectionRow(function() + ui.field.text{ + attr = { id = "username_field" }, + label = _'Login name', + name = 'login', + value = '' + } + ui.script{ script = 'document.getElementById("username_field").focus();' } + ui.field.password{ + label = _'Password', + name = 'password', + value = '' + } + ui.container { attr = { class = "actions" }, content = function() + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _'Login' + }, + content = "" + } + slot.put("
") + slot.put("
") + ui.link{ module = "index", view = "reset_password", text = _"Forgot password?" } + slot.put("  ") + ui.link{ module = "index", view = "send_login", text = _"Forgot login name?" } + end } + end ) end } +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/notifications.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/notifications.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,14 @@ +if app.session.member then + ui.title(_"Notifications") + + ui.section( function() + + ui.sectionHead( function() + ui.heading{ level = 1, content = _"Notifications" } + end ) + + ui.sectionRow( function() + execute.view { module = "index", view = "_sidebar_notifications" } + end ) + end ) +end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/register.lua --- a/app/main/index/register.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/register.lua Thu Jul 10 01:19:48 2014 +0200 @@ -7,7 +7,7 @@ local login = param.get("login") ui.form{ - attr = { class = "vertical" }, + attr = { class = "section vertical" }, module = 'index', action = 'register', params = { @@ -19,30 +19,27 @@ content = function() if not code then + ui.field.hidden{ name = "step", value = 1 } ui.title(_"Registration (step 1 of 3: Invite code)") - ui.actions(function() + ui.sectionHead( function() + ui.heading { level = 1, content = _"Please enter the invite code you've received" } + end ) + ui.sectionRow( function() + ui.field.text{ + label = _'Invite code', + name = 'code', + value = param.get("invite") + } + ui.submit{ + text = _'proceed with registration' + } + slot.put(" ") ui.link{ - content = function() - slot.put(_"Cancel registration") - end, + content = _"cancel registration", module = "index", view = "index" } - end) - ui.field.hidden{ name = "step", value = 1 } - ui.tag{ - tag = "p", - content = _"Please enter the invite code you've received." - } - ui.field.text{ - label = _'Invite code', - name = 'code', - value = param.get("invite") - } - ui.submit{ - text = _'Proceed with registration' - } - + end ) else local member = Member:new_selector() :add_where{ "invite_code = ?", code } @@ -53,79 +50,145 @@ if not member.notify_email and not notify_email or not member.name and not name or not member.login and not login or step == 1 then ui.title(_"Registration (step 2 of 3: Personal information)") ui.field.hidden{ name = "step", value = 2 } - ui.actions(function() + + ui.sectionHead( function() + ui.heading { level = 1, content = _"Check and enter personal data" } + end ) + ui.sectionRow( function() + ui.tag{ + tag = "p", + content = _"This invite key is connected with the following information:" + } + + execute.view{ module = "member", view = "_profile", params = { member = member, for_registration = true } } + + if not config.locked_profile_fields.notify_email then + ui.tag{ + tag = "p", + content = _"Please enter your email address. This address will be used for automatic notifications (if you request them) and in case you've lost your password. This address will not be published. After registration you will receive an email with a confirmation link." + } + ui.field.text{ + label = _'Email address', + name = 'notify_email', + value = param.get("notify_email") or member.notify_email + } + end + if not config.locked_profile_fields.name then + ui.tag{ + tag = "p", + content = _"Please choose a name, i.e. your real name or your nick name. This name will be shown to others to identify you." + } + ui.field.text{ + label = _'Screen name', + name = 'name', + value = param.get("name") or member.name + } + end + if not config.locked_profile_fields.login then + ui.tag{ + tag = "p", + content = _"Please choose a login name. This name will not be shown to others and is used only by you to login into the system. The login name is case sensitive." + } + ui.field.text{ + label = _'Login name', + name = 'login', + value = param.get("login") or member.login + } + end + ui.submit{ + text = _'proceed with registration' + } + slot.put(" ") ui.link{ - content = function() - slot.put(_"One step back") - end, + content = _"one step back", module = "index", view = "register", params = { invite = code } } - slot.put(" · ") + slot.put(" ") ui.link{ - content = function() - slot.put(_"Cancel registration") - end, + content = _"cancel registration", module = "index", view = "index" } - end) - - ui.tag{ - tag = "p", - content = _"This invite key is connected with the following information:" - } - - execute.view{ module = "member", view = "_profile", params = { member = member, include_private_data = true } } - - if not config.locked_profile_fields.notify_email then - ui.tag{ - tag = "p", - content = _"Please enter your email address. This address will be used for automatic notifications (if you request them) and in case you've lost your password. This address will not be published. After registration you will receive an email with a confirmation link." - } - ui.field.text{ - label = _'Email address', - name = 'notify_email', - value = param.get("notify_email") or member.notify_email - } - end - if not config.locked_profile_fields.name then - ui.tag{ - tag = "p", - content = _"Please choose a name, i.e. your real name or your nick name. This name will be shown to others to identify you." - } - ui.field.text{ - label = _'Screen name', - name = 'name', - value = param.get("name") or member.name - } - end - if not config.locked_profile_fields.login then - ui.tag{ - tag = "p", - content = _"Please choose a login name. This name will not be shown to others and is used only by you to login into the system. The login name is case sensitive." - } - ui.field.text{ - label = _'Login name', - name = 'login', - value = param.get("login") or member.login - } - end - ui.submit{ - text = _'Proceed with registration' - } + end ) else ui.field.hidden{ name = "step", value = "3" } ui.title(_"Registration (step 3 of 3: Terms of use and password)") - ui.actions(function() - ui.link{ + ui.sectionHead( function() + ui.heading { level = 1, content = _"Read and accept the terms and choose a password" } + end ) + ui.sectionRow( function() + ui.container{ + attr = { class = "wiki use_terms" }, content = function() - slot.put(_"One step back") - end, + slot.put(config.use_terms) + end + } + + member.notify_email = notify_email or member.notify_email + member.name = name or member.name + member.login = login or member.login + + execute.view{ module = "member", view = "_profile", params = { + member = member, include_private_data = true + } } + + for i, checkbox in ipairs(config.use_terms_checkboxes) do + slot.put("
") + ui.tag{ + tag = "div", + content = function() + ui.tag{ + tag = "input", + attr = { + type = "checkbox", + id = "use_terms_checkbox_" .. checkbox.name, + name = "use_terms_checkbox_" .. checkbox.name, + value = "1", + style = "float: left;", + checked = param.get("use_terms_checkbox_" .. checkbox.name, atom.boolean) and "checked" or nil + } + } + slot.put(" ") + ui.tag{ + tag = "label", + attr = { ['for'] = "use_terms_checkbox_" .. checkbox.name }, + content = function() slot.put(checkbox.html) end + } + end + } + end + + slot.put("
") + + ui.tag{ + tag = "p", + content = _"Please choose a password and enter it twice. The password is case sensitive." + } + ui.field.text{ + readonly = true, + label = _'Login name', + name = 'login', + value = member.login + } + ui.field.password{ + label = _'Password', + name = 'password1', + } + ui.field.password{ + label = _'Password (repeat)', + name = 'password2', + } + ui.submit{ + text = _'activate account' + } + slot.put(" ") + ui.link{ + content = _"one step back", module = "index", view = "register", params = { @@ -136,83 +199,13 @@ step = 1 } } - slot.put(" · ") + slot.put(" ") ui.link{ - content = function() - slot.put(_"Cancel registration") - end, + content = _"cancel registration", module = "index", view = "index" } - end) - ui.container{ - attr = { class = "wiki use_terms" }, - content = function() - if config.use_terms_html then - slot.put(config.use_terms_html) - else - slot.put(format.wiki_text(config.use_terms)) - end - end - } - - member.notify_email = notify_email or member.notify_email - member.name = name or member.name - member.login = login or member.login - - execute.view{ module = "member", view = "_profile", params = { - member = member, include_private_data = true - } } - - for i, checkbox in ipairs(config.use_terms_checkboxes) do - slot.put("
") - ui.tag{ - tag = "div", - content = function() - ui.tag{ - tag = "input", - attr = { - type = "checkbox", - id = "use_terms_checkbox_" .. checkbox.name, - name = "use_terms_checkbox_" .. checkbox.name, - value = "1", - style = "float: left;", - checked = param.get("use_terms_checkbox_" .. checkbox.name, atom.boolean) and "checked" or nil - } - } - slot.put(" ") - ui.tag{ - tag = "label", - attr = { ['for'] = "use_terms_checkbox_" .. checkbox.name }, - content = function() slot.put(checkbox.html) end - } - end - } - end - - slot.put("
") - - ui.tag{ - tag = "p", - content = _"Please choose a password and enter it twice. The password is case sensitive." - } - ui.field.text{ - readonly = true, - label = _'Login name', - name = 'login', - value = member.login - } - ui.field.password{ - label = _'Password', - name = 'password1', - } - ui.field.password{ - label = _'Password (repeat)', - name = 'password2', - } - ui.submit{ - text = _'Activate account' - } + end ) end end end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/reset_password.lua --- a/app/main/index/reset_password.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/reset_password.lua Thu Jul 10 01:19:48 2014 +0200 @@ -2,83 +2,123 @@ ui.title(_"Reset password") -ui.actions(function() - ui.link{ - content = function() - slot.put(_"Cancel") - end, - module = "index", - view = "login" - } -end) +ui.section( function() + + ui.sectionHead( function() + ui.heading{ level = 1, content = _"Reset password" } + end ) + + ui.sectionRow( function() -local secret = param.get("secret") + local secret = param.get("secret") -if not secret then - ui.tag{ - tag = 'p', - content = _'Please enter your login name. You will receive an email with a link to reset your password.' - } - ui.form{ - attr = { class = "vertical" }, - module = "index", - action = "reset_password", - routing = { - ok = { - mode = "redirect", - module = "index", - view = "index" - } - }, - content = function() - ui.field.text{ - label = _"login name", - name = "login" - } - ui.submit{ text = _"Request password reset link" } - slot.put("  ") - ui.link{ module = "index", view = "send_login", text = _"Forgot login name?" } - end - } - -else - - ui.form{ - attr = { class = "vertical" }, - module = "index", - action = "reset_password", - routing = { - ok = { - mode = "redirect", - module = "index", - view = "index" - } - }, - content = function() + if not secret then ui.tag{ tag = 'p', - content = _'Please enter the email reset code you have received:' + content = _'Please enter your login name. You will receive an email with a link to reset your password.' } - ui.field.text{ - label = _"Reset code", - name = "secret", - value = secret - } - ui.tag{ - tag = 'p', - content = _'Please enter your new password twice.' + ui.form{ + attr = { class = "vertical" }, + module = "index", + action = "reset_password", + routing = { + ok = { + mode = "redirect", + module = "index", + view = "index" + } + }, + content = function() + ui.field.text{ + label = _"login name", + name = "login" + } + + ui.container { attr = { class = "actions" }, content = function() + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Request password reset link" + }, + content = "" + } + slot.put("

") + ui.link{ module = "index", view = "send_login", text = _"Forgot login name?" } + slot.put("  ") + ui.link{ + content = function() + slot.put(_"Cancel") + end, + module = "index", + view = "login" + } + end } + end } - ui.field.password{ - label = "New password", - name = "password1" + + else + + ui.form{ + attr = { class = "vertical" }, + module = "index", + action = "reset_password", + routing = { + ok = { + mode = "redirect", + module = "index", + view = "index" + } + }, + content = function() + ui.tag{ + tag = 'p', + content = _'Please enter the email reset code you have received:' + } + ui.field.text{ + label = _"Reset code", + name = "secret", + value = secret + } + ui.tag{ + tag = 'p', + content = _'Please enter your new password twice.' + } + ui.field.password{ + label = "New password", + name = "password1" + } + ui.field.password{ + label = "New password (repeat)", + name = "password2" + } + + ui.container { attr = { class = "actions" }, content = function() + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Save new password" + }, + content = "" + } + slot.put("
") + slot.put("
") + + ui.link{ + content = function() + slot.put(_"Cancel") + end, + module = "index", + view = "login" + } + end } + end } - ui.field.password{ - label = "New password (repeat)", - name = "password2" - } - ui.submit{ text = _"Set new password" } + end - } - -end \ No newline at end of file + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/search.lua --- a/app/main/index/search.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/search.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,65 +1,104 @@ local search_for = param.get("search_for", atom.string) or "global" -local search_string = param.get("search", atom.string) +local search_string = param.get("q", atom.string) if search_string then - slot.put_into("title", encode.html(_("Search results for: '#{search}'", { search = search_string }))) + ui.title ( _("Search results for: '#{search}'", { search = search_string } ) ) else - slot.put_into("title", encode.html(_"Search")) + ui.title ( _"Search" ) end ui.form{ method = "get", module = "index", view = "search", routing = { default = { mode = "redirect", - module = "index", view = "search", search_for = search_for, search = search_string + module = "index", view = "search", search_for = search_for, q = search_string } }, - attr = { class = "vertical" }, + attr = { class = "vertical section" }, content = function() - - if app.session:has_access("everything") then - ui.field.select{ - label = _"Search context", - name = "search_for", - value = search_for, - foreign_records = { - { id = "global", name = _"Global search" }, - { id = "member", name = _"Search for members" }, - { id = "issue", name = _"Search for issues" } - }, - foreign_id = "id", - foreign_name = "name", + + ui.sectionHead( function() + ui.heading { level = 1, content = _"Search" } + end) + + ui.sectionRow( function() + ui.tag { content = _"Search term (only complete words)" } + ui.tag { + tag = "input", + attr = { + name = "q", + value = search_string + } } - end - ui.field.text{ label = _"Search term (only complete words)", name = "search", value = search_string } - ui.submit{ value = _"Start search" } + ui.tag{ + tag = "input", + attr = { + class = "btn btn-search", + type = "submit", + value = _"search" + } + } + end ) end } -slot.put("
") -if search_string then +if not search_string then + return +end + - if app.session:has_access("everything") then - if search_for == "global" or search_for == "member" then - local members_selector = Member:get_search_selector(search_string) +local members_selector = Member:get_search_selector(search_string) +local count = members_selector:count() +local text +if count == 0 then + text = _"No matching members found" +elseif count == 1 then + text = _"1 matching member found" +else + text = _"#{count} matching members found" +end +if app.session:has_access("everything") then + ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = _(text, { count = count }) } + end ) + if count > 0 then execute.view{ module = "member", view = "_list", - params = { members_selector = members_selector }, + params = { + members_selector = members_selector, + no_filter = true + }, } end - end + end ) +end + +slot.put("
") + +local issues_selector = Issue:get_search_selector(search_string) +local count = issues_selector:count() +local text +if count == 0 then + text = _"No matching issues found" +elseif count == 1 then + text = _"1 matching issue found" +else + text = _"#{count} matching issues found" +end - if search_for == "global" or search_for == "issue" then - local issues_selector = Issue:get_search_selector(search_string) +ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = _(text, { count = count }) } + end ) + if count > 0 then execute.view{ module = "issue", - view = "_list", + view = "_list2", params = { - issues_selector = issues_selector, - highlight_string = search_string, + search = search_string, no_filter = true }, } end - -end +end) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/send_login.lua --- a/app/main/index/send_login.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/send_login.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,35 +1,54 @@ -ui.title(_"Request email with login name") +ui.title(_"Recover login name") + +ui.section( function() -ui.actions(function() - ui.link{ - content = function() - slot.put(_"Cancel") - end, - module = "index", - view = "login" - } -end) + ui.sectionHead( function() + ui.heading{ level = 1, content = _"Request email with login name" } + end ) + + ui.sectionRow( function() -ui.tag{ - tag = 'p', - content = _'Please enter your email address. You will receive an email with your login name.' -} -ui.form{ - attr = { class = "vertical" }, - module = "index", - action = "send_login", - routing = { - ok = { - mode = "redirect", + ui.tag{ + tag = 'p', + content = _'Please enter your email address. You will receive an email with your login name.' + } + ui.form{ + attr = { class = "vertical" }, module = "index", - view = "index" + action = "send_login", + routing = { + ok = { + mode = "redirect", + module = "index", + view = "index" + } + }, + content = function() + ui.field.text{ + label = _"Email address", + name = "email" + } + + ui.container { attr = { class = "actions" }, content = function() + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Request email with login name" + }, + content = "" + } + slot.put("

") + ui.link{ + content = function() + slot.put(_"Cancel") + end, + module = "index", + view = "login" + } + end } + end } - }, - content = function() - ui.field.text{ - label = _"Email address", - name = "email" - } - ui.submit{ text = _"Request email with login name" } - end -} + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/index/usage_terms.lua --- a/app/main/index/usage_terms.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/index/usage_terms.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,8 +1,19 @@ -slot.put("
") +ui.title(_"Terms of use") + +ui.section( function() + + ui.sectionHead( function() + ui.heading { level = 1, content = _"Terms of use" } + end ) + + ui.sectionRow( function() -ui.container{ - attr = { class = "wiki use_terms" }, - content = function() - slot.put(format.wiki_text(config.use_terms)) - end -} + ui.container{ + attr = { class = "wiki use_terms" }, + content = function() + slot.put(config.use_terms) + end + } + + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_action/add_support.lua --- a/app/main/initiative/_action/add_support.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/_action/add_support.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,6 +1,8 @@ local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec() local auto_support = param.get("auto_support", atom.boolean) +local draft_id = param.get("draft_id", atom.integer) + -- TODO important m1 selectors returning result _SET_! local issue = initiative:get_reference_selector("issue"):for_share():single_object_mode():exec() @@ -37,6 +39,13 @@ :limit(1) :single_object_mode() :exec() + +if draft_id and draft_id ~= last_draft.id then + slot.select("error", function() + ui.tag{ content = _"The initiative draft has been updated again in the meanwhile, support not updated!" } + end) + return false +end if not supporter then supporter = Supporter:new() @@ -47,12 +56,11 @@ supporter.auto_support = auto_support end 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") + 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") + slot.put_into("notice", _"You are already supporting the latest draft") end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_action/create.lua --- a/app/main/initiative/_action/create.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/_action/create.lua Thu Jul 10 01:19:48 2014 +0200 @@ -73,23 +73,32 @@ local name = util.trim(name) if #name < 3 then - slot.put_into("error", _"This name is really too short!") + slot.put_into("error", _"Please enter a meaningful title for your initiative!") + return false +end + +if #name > 140 then + slot.put_into("error", _"This title is too long!") return false end -local formatting_engine = param.get("formatting_engine") - -local formatting_engine_valid = false -for fe, dummy in pairs(config.formatting_engine_executeables) do - if formatting_engine == fe then - formatting_engine_valid = true +local formatting_engine +if config.enforce_formatting_engine then + formatting_engine = config.enforce_formatting_engine +else + formatting_engine = param.get("formatting_engine") + local formatting_engine_valid = false + for i, fe in ipairs(config.formatting_engines) do + if formatting_engine == fe.id then + formatting_engine_valid = true + end + end + if not formatting_engine_valid then + error("invalid formatting engine!") end end -if not formatting_engine_valid then - error("invalid formatting engine!") -end -if param.get("preview") then +if param.get("preview") or param.get("edit") then return end @@ -155,7 +164,6 @@ end initiative.issue_id = issue.id initiative.name = name -param.update(initiative, "discussion_url") initiative:save() local draft = Draft:new() diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_action/remove_support.lua --- a/app/main/initiative/_action/remove_support.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/_action/remove_support.lua Thu Jul 10 01:19:48 2014 +0200 @@ -23,7 +23,5 @@ 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 a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_bargraph.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_bargraph.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,61 @@ +local initiative = param.get("initiative", "table") +local batteled_initiative = param.get("battled_initiative", "table") + +local grey = "#eee" + +if initiative.issue.fully_frozen and initiative.issue.closed + and initiative.negative_votes and initiative.positive_votes and initiative.rank ~= 1 then + if not batteled_initiative then + return + end + local battle1 = Battle:getByInitiativeIds(batteled_initiative.id, initiative.id) + local battle2 = Battle:getByInitiativeIds(initiative.id, batteled_initiative.id) + + if not battle1 or not battle2 then + return + end + + local positive_votes = battle2.count + local negative_votes = battle1.count + + local max_value = initiative.issue.voter_count + if max_value > 0 then + ui.bargraph{ + max_value = max_value * 2, + width = 100, + bars = { + { color = grey, value = max_value - negative_votes }, + { color = "#a00", value = negative_votes }, + { color = "#0a0", value = positive_votes }, + { color = grey, value = max_value - positive_votes }, + } + } + else + ui.bargraph{ + max_value = 1, + width = 100, + bars = { + { color = grey, value = 1 }, + } + } + end +else + local max_value = initiative.issue.population or 0 + local quorum + if initiative.issue.accepted then + quorum = initiative.issue.policy.initiative_quorum_num / initiative.issue.policy.initiative_quorum_den + else + quorum = initiative.issue.policy.issue_quorum_num / initiative.issue.policy.issue_quorum_den + end + ui.bargraph{ + max_value = max_value, + width = 100, + quorum = max_value * quorum, + quorum_color = "#00F", + bars = { + { color = "#5a5", value = (initiative.satisfied_supporter_count or 0) }, + { color = "#fa5", value = (initiative.supporter_count or 0) - (initiative.satisfied_supporter_count or 0) }, + { color = grey, value = max_value - (initiative.supporter_count or 0) }, + } + } +end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_battles.lua --- a/app/main/initiative/_battles.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/_battles.lua Thu Jul 10 01:19:48 2014 +0200 @@ -19,6 +19,7 @@ :count() if number_of_initiatives > 1 then + ui.heading { level = 1, content = _"Preference comparison" } ui.list{ records = battled_initiatives, columns = { diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_head.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_head.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,198 @@ +local initiative = param.get("initiative", "table") +local member = param.get("member", "table") or app.session.member + +-- TODO performance +local initiator +if member then + initiator = Initiator:by_pk(initiative.id, member.id) +end + +local initiators_members_selector = initiative:get_reference_selector("initiating_members") + :add_field("initiator.accepted", "accepted") + :add_order_by("member.name") +if initiator and initiator.accepted then + initiators_members_selector:add_where("initiator.accepted ISNULL OR initiator.accepted") +else + initiators_members_selector:add_where("initiator.accepted") +end + +local initiators = initiators_members_selector:exec() + + +ui.sectionHead( "initiativeInfo", function () + + ui.heading { + level = 1, + content = initiative.display_name + } + + ui.container { attr = { class = "support" }, content = function () + if initiative.supporter_count == nil then + ui.tag { + attr = { class = "supporterCount" }, + content = _"[calculating]" + } + elseif initiative.issue.closed == nil then + ui.tag { + attr = { class = "satisfiedSupporterCount" }, + content = _("#{count} supporter", { count = initiative.satisfied_supporter_count }) + } + if initiative.potential_supporter_count and + initiative.potential_supporter_count > 0 + then + slot.put ( " " ) + ui.tag { + attr = { class = "potentialSupporterCount" }, + content = _("(+ #{count} potential)", { count = initiative.potential_supporter_count }) + } + end + + end + + slot.put ( "
" ) + + execute.view { + module = "initiative", view = "_bargraph", params = { + initiative = initiative + } + } + end } + + if member then + ui.container { attr = { class = "mySupport right" }, content = function () + if initiative.issue.fully_frozen then + if initiative.issue.member_info.direct_voted then + --ui.image { attr = { class = "icon48 right" }, static = "icons/48/voted_ok.png" } + ui.tag { content = _"You have voted" } + slot.put("
") + if not initiative.issue.closed then + ui.link { + module = "vote", view = "list", + params = { issue_id = initiative.issue.id }, + text = _"change vote" + } + else + ui.link { + module = "vote", view = "list", + params = { issue_id = initiative.issue.id }, + text = _"show vote" + } + end + slot.put(" ") + elseif active_trustee_id then + ui.tag { content = _"You have voted via delegation" } + ui.link { + content = _"Show voting ballot", + module = "vote", view = "list", params = { + issue_id = initiative.issue.id, member_id = active_trustee_id + } + } + elseif not initiative.issue.closed then + ui.link { + attr = { class = "btn btn-default" }, + module = "vote", view = "list", + params = { issue_id = initiative.issue.id }, + text = _"vote now" + } + end + elseif initiative.member_info.supported then + if initiative.member_info.satisfied then + ui.image { attr = { class = "icon48 right" }, static = "icons/32/support_satisfied.png" } + else + ui.image { attr = { class = "icon48 right" }, static = "icons/32/support_unsatisfied.png" } + end + ui.container { content = _"You are supporter" } + + if initiative.issue.member_info.own_participation then + ui.link { + attr = { class = "btn-link" }, + module = "initiative", action = "remove_support", + routing = { default = { + mode = "redirect", module = "initiative", view = "show", id = initiative.id + } }, + id = initiative.id, + text = "remove my support" + } + + else + + ui.link { + module = "delegation", view = "show", params = { + issue_id = initiative.issue_id, + initiative_id = initiative.id + }, + content = _"via delegation" + } + + end + + slot.put(" ") + + + else + ui.link { + attr = { class = "btn btn-default" }, + module = "initiative", action = "add_support", + routing = { default = { + mode = "redirect", module = "initiative", view = "show", id = initiative.id + } }, + id = initiative.id, + text = _"add my support" + } + + end + end } + + end + + slot.put("
") + + ui.container { + attr = { class = "initiators" }, + content = function () + + if app.session:has_access("authors_pseudonymous") then + for i, member in ipairs(initiators) do + if i > 1 then + slot.put(" ") + end + util.micro_avatar(member) + if member.accepted == nil then + slot.put ( " " ) + ui.tag { content = _"(invited)" } + end + end -- for i, member + + end + + end + } -- ui.container "initiators" + + ui.container { + attr = { class = "links" }, + content = function () + + local drafts_count = initiative:get_reference_selector("drafts"):count() + ui.link { + content = _("suggestions (#{count}) ↓", { + count = # ( initiative.suggestions ) + }), + external = "#suggestions" + } + + slot.put ( " | " ) + + ui.link{ + module = "initiative", view = "history", id = initiative.id, + content = _("draft history (#{count})", { count = drafts_count }) + } + + end + } -- ui.containers "links" + end ) + + execute.view { + module = "initiative", view = "_sidebar_state", + params = { initiative = initiative } + } + diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_initiators.lua --- a/app/main/initiative/_initiators.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -local initiative = param.get("initiative", "table") -local initiator = param.get("initiator", "table") -local initiators_members_selector = param.get("initiators_members_selector", "table") - -local initiator_count = initiators_members_selector:count() - -if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then - ui.link{ - attr = { class = "action" }, - content = function() - ui.image{ static = "icons/16/user_add.png" } - slot.put(_"Invite initiator") - end, - module = "initiative", - view = "add_initiator", - params = { initiative_id = initiative.id } - } - if initiator_count > 1 then - ui.link{ - content = function() - ui.image{ static = "icons/16/user_delete.png" } - slot.put(_"Remove initiator") - end, - module = "initiative", - view = "remove_initiator", - params = { initiative_id = initiative.id } - } - end -end -if initiator and initiator.accepted == false then - ui.link{ - image = { static = "icons/16/user_delete.png" }, - text = _"Cancel refuse of invitation", - module = "initiative", - action = "remove_initiator", - params = { - initiative_id = initiative.id, - member_id = app.session.member.id - }, - routing = { - ok = { - mode = "redirect", - module = "initiative", - view = "show", - id = initiative.id - } - } - } -end - -execute.view{ - module = "member", - view = "_list", - params = { - members_selector = initiators_members_selector, - initiator = initiator - } -} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_list.lua --- a/app/main/initiative/_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,79 +1,79 @@ -local issue = param.get("issue", "table") -local initiatives_selector = param.get("initiatives_selector", "table") +local member = param.get("member", "table") or app.session.member -local initiatives -if issue then - initiatives = issue.initiatives -else - initiatives = initiatives_selector:exec() - initiatives:load_everything_for_member_id(app.session.member_id) -end - -local highlight_initiative = param.get("highlight_initiative", "table") - -local for_member = param.get("for_member", "table") or app.session.member +local initiatives = param.get("initiatives", "table") +local highlight_initiative_id = param.get ( "highlight_initiative_id", "number" ) -local limit = param.get("limit", atom.number) -local hide_more_initiatives = param.get("hide_more_initiatives", atom.boolean) +local for_initiative = param.get("initiative", "table") -local more_initiatives_count -if limit then - if #initiatives > limit then - more_initiatives_count = #initiatives - limit - end - initiatives = {} - for i, initiative in ipairs(issue.initiatives) do - if i <= limit then - initiatives[#initiatives+1] = initiative - end - end -end +local for_event = param.get("for_event", atom.boolean) -local name = "initiative_list" -if issue then - name = "issue_" .. tostring(issue.id) .. "_initiative_list" +if for_initiative then + initiatives = { for_initiative } end -ui.add_partial_param_names{ name } +ui.tag { + tag = "ul", + attr = { class = "initiatives" }, + content = function () + local last_group + for i, initiative in ipairs(initiatives) do + local group + if initiative.issue.closed then + if initiative.rank == 1 then + group = "1st_rank" + elseif initiative.admitted then + group = "admitted" + elseif initiative.revoked_by_member_id then + group = "revoked" + else + group = "not_admitted" + end + end + if not for_initiative and group ~= last_group and not for_event then -if highlight_initiative then - local highlight_initiative_found - for i, initiative in ipairs(initiatives) do - if initiative.id == highlight_initiative.id then - highhighlight_initiative_found = true - end - end - if not highhighlight_initiative_found then - initiatives[#initiatives+1] = highlight_initiative - if more_initiatives_count then - more_initiatives_count = more_initiatives_count - 1 + local text + if group == "admitted" then + if initiative.issue.state == "finished_with_winner" then + text = _"Competing initiatives in pairwise comparison to winner:" + else + text = _"Competing initiatives in pairwise comparison to best initiative:" + end + end + if group == "not_admitted" then + text = _("Competing initiatives failed the 2nd quorum (#{num}/#{den}):", { + num = initiative.issue.policy.initiative_quorum_num, + den = initiative.issue.policy.initiative_quorum_den + } ) + end + if text then + slot.put("
") + ui.container { attr = { class = "result" }, content = text } + end + last_group = group + end + + local class = "" + if highlight_initiative_id == initiative.id then + class = "highlighted" + end + if app.session.member then + if initiative.member_info.supported then + class = class .. " supported" + end + if initiative.member_info.satisfied then + class = class .. " satisfied" + end + end + ui.tag { + tag = "li", attr = { class = class }, + content = function () + execute.view { + module = "initiative", view = "_list_element", params = { + initiative = initiative, for_event = for_event + } + } + end + } end - end -end -for i, initiative in ipairs(initiatives) do - execute.view{ - module = "initiative", - view = "_list_element", - params = { - initiative = initiative, - selected = highlight_initiative and highlight_initiative.id == initiative.id or nil, - for_member = for_member - } - } -end - -if not hide_more_initiatives and more_initiatives_count and more_initiatives_count > 0 then - local text - if more_initiatives_count == 1 then - text = _("and one more initiative") - else - text = _("and #{count} more initiatives", { count = more_initiatives_count }) - end - ui.link{ - attr = { class = "more_initiatives_link" }, - content = text, - module = "issue", - view = "show", - id = issue.id, - } -end + end +} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_list_element.lua --- a/app/main/initiative/_list_element.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/_list_element.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,152 +1,110 @@ local initiative = param.get("initiative", "table") -local selected = param.get("selected", atom.boolean) -local for_member = param.get("for_member", "table") or app.session.member +local for_event = param.get("for_event", atom.boolean) + +local issue = initiative.issue local class = "initiative" -if selected then - class = class .. " selected" +if initiative.rank == 1 then + class = class .. " rank1" end -if initiative.polling then - class = class .. " polling" +if initiative.revoked then + class = class .. " revoked" end -ui.container{ attr = { class = class }, content = function() - - ui.container{ attr = { class = "rank" }, content = function() - if initiative.issue.fully_frozen and initiative.issue.closed - or initiative.admitted == false - then - ui.field.rank{ attr = { class = "rank" }, value = initiative.rank, eligible = initiative.eligible } - elseif not initiative.issue.closed then - ui.image{ static = "icons/16/script.png" } - else - ui.image{ static = "icons/16/cross.png" } - end - end } - - ui.container{ attr = { class = "bar" }, content = function() - if initiative.issue.fully_frozen and initiative.issue.closed then - if initiative.negative_votes and initiative.positive_votes then - local max_value = initiative.issue.voter_count - ui.bargraph{ - max_value = max_value, - width = 100, - bars = { - { color = "#0a5", value = initiative.positive_votes }, - { color = "#aaa", value = max_value - initiative.negative_votes - initiative.positive_votes }, - { color = "#a00", value = initiative.negative_votes }, - } - } - else - slot.put(" ") - end - else - local max_value = initiative.issue.population or 0 - local quorum - if initiative.issue.accepted then - quorum = initiative.issue.policy.initiative_quorum_num / initiative.issue.policy.initiative_quorum_den - else - quorum = initiative.issue.policy.issue_quorum_num / initiative.issue.policy.issue_quorum_den - end - ui.bargraph{ - max_value = max_value, - width = 100, - quorum = max_value * quorum, - quorum_color = "#00F", - bars = { - { color = "#0a5", value = (initiative.satisfied_supporter_count or 0) }, - { color = "#aaa", value = (initiative.supporter_count or 0) - (initiative.satisfied_supporter_count or 0) }, - { color = "#fff", value = max_value - (initiative.supporter_count or 0) }, +ui.container{ + attr = { class = class }, + content = function () + if initiative.rank ~= 1 and not for_event then + execute.view { + module = "initiative", view = "_bargraph", params = { + initiative = initiative, + battled_initiative = issue.initiatives[1] } } + slot.put(" ") end - end } - - if app.session.member_id then - ui.container{ attr = { class = "interest" }, content = function() - if initiative.member_info.initiated then - local label - if for_member and for_member.id ~= app.session.member_id then - label = _"This member is initiator of this initiative" - else - label = _"You are initiator of this initiative" - end - ui.image{ - attr = { alt = label, title = label }, - static = "icons/16/user_edit.png" + ui.tag { + attr = { class = "initiative_name" }, + content = function() + ui.link { + text = initiative.display_name, + module = "initiative", view = "show", id = initiative.id } - elseif initiative.member_info.directly_supported then - if initiative.member_info.satisfied then - if for_member and for_member.id ~= app.session.member_id then - label = _"This member is supporter of this initiative" - else - local label = _"You are supporter of this initiative" + slot.put(" ") + if initiative.vote_grade ~= nil then + if initiative.vote_grade > 0 then + local text = _"voted yes" + ui.image { attr = { class = "icon16", title = text, alt = text }, static = "icons/32/support_satisfied.png" } + elseif initiative.vote_grade == 0 then + elseif initiative.vote_grade < 0 then + local text = _"voted no" + ui.image { attr = { class = "icon16", title = text, alt = text }, static = "icons/32/voted_no.png" } end - ui.image{ - attr = { alt = label, title = label }, - static = "icons/16/thumb_up_green.png" - } - else - if for_member and for_member.id ~= app.session.member_id then - label = _"This member is potential supporter of this initiative" - else - local label = _"You are potential supporter of this initiative" + elseif app.session.member then + if initiative.member_info.supported then + if initiative.member_info.satisfied then + local text = _"supporter" + ui.image { attr = { class = "icon16", title = text, alt = text }, static = "icons/32/support_satisfied.png" } + else + local text = _"supporter with restricting suggestions" + ui.image { attr = { class = "icon16", title = text, alt = text }, static = "icons/32/support_unsatisfied.png" } + end end - ui.image{ - attr = { alt = label, title = label }, - static = "icons/16/thumb_up.png" - } - end - elseif initiative.member_info.supported then - if initiative.member_info.satisfied then - if for_member and for_member.id ~= app.session.member_id then - label = _"This member is supporter of this initiative via delegation" - else - local label = _"You are supporter of this initiative via delegation" - end - ui.image{ - attr = { alt = label, title = label }, - static = "icons/16/thumb_up_green_arrow.png" - } - else - if for_member and for_member.id ~= app.session.member_id then - label = _"This member is potential supporter of this initiative via delegation" - else - local label = _"You are potential supporter of this initiative via delegation" - end - ui.image{ - attr = { alt = label, title = label }, - static = "icons/16/thumb_up_arrow.png" - } end end - end } + } + end - - ui.container{ attr = { class = "name" }, content = function() - local link_class = "initiative_link" - if initiative.revoked then - link_class = "revoked" +} + +if initiative.rank == 1 + and issue.voter_count + and initiative.positive_votes ~= nil + and initiative.negative_votes ~= nil + and not for_event +then + function percent(p, q) + if q > 0 then + return math.floor(p / q * 100) .. "%" + else + return "0%" end - ui.link{ - attr = { class = link_class }, - content = function() - local name - if initiative.name_highlighted then - name = encode.highlight(initiative.name_highlighted) - else - name = encode.html(initiative.shortened_name) - end - ui.tag{ content = "i" .. initiative.id .. ": " } - slot.put(name) - end, - module = "initiative", - view = "show", - id = initiative.id - } - - end } + end + local result = "" + if initiative.eligible then + result = _("Reached #{sign}#{num}/#{den}", { + sign = issue.policy.direct_majority_strict and ">" or "≥", + num = issue.policy.direct_majority_num, + den = issue.policy.direct_majority_den + }) + else + result = _("Failed #{sign}#{num}/#{den}", { + sign = issue.policy.direct_majority_strict and ">" or "≥", + num = issue.policy.direct_majority_num, + den = issue.policy.direct_majority_den + }) + end + local neutral_count = issue.voter_count - initiative.positive_votes - initiative.negative_votes + + local result_text + + if issue.voter_count > 0 then + result_text = _("#{result}: #{yes_count} Yes (#{yes_percent}), #{no_count} No (#{no_percent}), #{neutral_count} Abstention (#{neutral_percent})", { + result = result, + yes_count = initiative.positive_votes, + yes_percent = percent(initiative.positive_votes, issue.voter_count), + neutral_count = neutral_count, + neutral_percent = percent(neutral_count, issue.voter_count), + no_count = initiative.negative_votes, + no_percent = percent(initiative.negative_votes, issue.voter_count) + }) + else + result_text = _("#{result}: No votes (0)", { result = result }) + end + + ui.container { attr = { class = "result" }, content = result_text } -end } +end + diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_show.lua --- a/app/main/initiative/_show.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,531 +0,0 @@ -local initiative = param.get("initiative", "table") - -local show_as_head = param.get("show_as_head", atom.boolean) - -initiative:load_everything_for_member_id(app.session.member_id) - -local issue = initiative.issue - --- TODO performance -local initiator -if app.session.member_id then - initiator = Initiator:by_pk(initiative.id, app.session.member.id) -end - -if app.session.member_id then - issue:load_everything_for_member_id(app.session.member_id) -end - -app.html_title.title = initiative.name -app.html_title.subtitle = _("Initiative ##{id}", { id = initiative.id }) - -slot.select("head", function() - execute.view{ - module = "issue", view = "_head", - params = { issue = issue, initiative = initiative } - } -end) - -local initiators_members_selector = initiative:get_reference_selector("initiating_members") - :add_field("initiator.accepted", "accepted") - :add_order_by("member.name") -if initiator and initiator.accepted then - initiators_members_selector:add_where("initiator.accepted ISNULL OR initiator.accepted") -else - initiators_members_selector:add_where("initiator.accepted") -end - -local initiators = initiators_members_selector:exec() - - -local initiatives_selector = initiative.issue:get_reference_selector("initiatives") -slot.select("head", function() - execute.view{ - module = "issue", - view = "_show", - params = { - issue = initiative.issue, - initiative_limit = 3, - for_initiative = initiative - } - } -end) - -util.help("initiative.show") - -local class = "initiative_head" - -if initiative.polling then - class = class .. " polling" -end - -ui.container{ attr = { class = class }, content = function() - - local text = _("Initiative i#{id}: #{name}", { id = initiative.id, name = initiative.name }) - if show_as_head then - ui.link{ - attr = { class = "title" }, text = text, - module = "initiative", view = "show", id = initiative.id - } - else - ui.container{ attr = { class = "title" }, content = text } - end - if app.session:has_access("authors_pseudonymous") then - ui.container{ attr = { class = "content" }, content = function() - ui.tag{ - attr = { class = "initiator_names" }, - content = function() - for i, initiator in ipairs(initiators) do - slot.put(" ") - if app.session:has_access("all_pseudonymous") then - ui.link{ - content = function () - execute.view{ - module = "member_image", - view = "_show", - params = { - member = initiator, - image_type = "avatar", - show_dummy = true, - class = "micro_avatar", - popup_text = text - } - } - end, - module = "member", view = "show", id = initiator.id - } - slot.put(" ") - end - ui.link{ - text = initiator.name, - module = "member", view = "show", id = initiator.id - } - if not initiator.accepted then - ui.tag{ attr = { title = _"Not accepted yet" }, content = "?" } - end - end - if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then - slot.put(" · ") - ui.link{ - attr = { class = "action" }, - content = function() - slot.put(_"Invite initiator") - end, - module = "initiative", - view = "add_initiator", - params = { initiative_id = initiative.id } - } - if #initiators > 1 then - slot.put(" · ") - ui.link{ - content = function() - slot.put(_"Remove initiator") - end, - module = "initiative", - view = "remove_initiator", - params = { initiative_id = initiative.id } - } - end - end - if initiator and initiator.accepted == false then - slot.put(" · ") - ui.link{ - text = _"Cancel refuse of invitation", - module = "initiative", - action = "remove_initiator", - params = { - initiative_id = initiative.id, - member_id = app.session.member.id - }, - routing = { - ok = { - mode = "redirect", - module = "initiative", - view = "show", - id = initiative.id - } - } - } - end - if (initiative.discussion_url and #initiative.discussion_url > 0) then - slot.put(" · ") - if initiative.discussion_url:find("^https?://") then - if initiative.discussion_url and #initiative.discussion_url > 0 then - ui.link{ - attr = { - target = "_blank", - title = _"Discussion with initiators" - }, - text = _"Discuss with initiators", - external = initiative.discussion_url - } - end - else - slot.put(encode.html(initiative.discussion_url)) - end - end - if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then - slot.put(" · ") - ui.link{ - text = _"change discussion URL", - module = "initiative", - view = "edit", - id = initiative.id - } - slot.put(" ") - end - end - } - end } - end - - if app.session.member_id then - ui.container{ attr = { class = "content" }, content = function() - execute.view{ - module = "supporter", - view = "_show_box", - params = { - initiative = initiative - } - } - end } - end - - - -- voting results - if initiative.issue.fully_frozen and initiative.issue.closed and initiative.admitted then - local class = initiative.winner and "admitted_info" or "not_admitted_info" - ui.container{ - attr = { class = class }, - content = function() - local max_value = initiative.issue.voter_count - slot.put(" ") - local positive_votes = initiative.positive_votes - local negative_votes = initiative.negative_votes - local sum_votes = initiative.positive_votes + initiative.negative_votes - local function perc(votes, sum) - if sum > 0 and votes > 0 then return " (" .. string.format( "%.f", votes * 100 / sum ) .. "%)" end - return "" - end - slot.put(_"Yes" .. ": " .. tostring(positive_votes) .. perc(positive_votes, sum_votes) .. "") - slot.put(" · ") - slot.put(_"Abstention" .. ": " .. tostring(max_value - initiative.negative_votes - initiative.positive_votes) .. "") - slot.put(" · ") - slot.put(_"No" .. ": " .. tostring(initiative.negative_votes) .. perc(negative_votes, sum_votes) .. "") - slot.put(" · ") - slot.put("") - if initiative.winner then - slot.put(_"Approved") - elseif initiative.rank then - slot.put(_("Not approved (rank #{rank})", { rank = initiative.rank })) - else - slot.put(_"Not approved") - end - slot.put("") - end - } - end - - ui.container{ attr = { class = "content" }, content = function() - execute.view{ - module = "initiative", - view = "_battles", - params = { initiative = initiative } - } - end } - - -- initiative not admitted info - if initiative.admitted == false then - local policy = initiative.issue.policy - ui.container{ - attr = { class = "not_admitted_info" }, - content = _("This initiative has not been admitted! It failed the quorum of #{quorum}.", { quorum = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den) }) - } - end - - -- initiative revoked info - if initiative.revoked then - ui.container{ - attr = { class = "revoked_info" }, - content = function() - slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) })) - local suggested_initiative = initiative.suggested_initiative - if suggested_initiative then - slot.put("

") - slot.put(_("The initiators suggest to support the following initiative:")) - slot.put(" ") - ui.link{ - content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name), - module = "initiative", - view = "show", - id = suggested_initiative.id - } - end - end - } - end - - - -- invited as initiator - if initiator and initiator.accepted == nil and not initiative.issue.half_frozen and not initiative.issue.closed then - ui.container{ - attr = { class = "initiator_invite_info" }, - content = function() - slot.put(_"You are invited to become initiator of this initiative.") - slot.put(" ") - ui.link{ - image = { static = "icons/16/tick.png" }, - text = _"Accept invitation", - module = "initiative", - action = "accept_invitation", - id = initiative.id, - routing = { - default = { - mode = "redirect", - module = request.get_module(), - view = request.get_view(), - id = param.get_id_cgi(), - params = param.get_all_cgi() - } - } - } - slot.put(" ") - ui.link{ - image = { static = "icons/16/cross.png" }, - text = _"Refuse invitation", - module = "initiative", - action = "reject_initiator_invitation", - params = { - initiative_id = initiative.id, - member_id = app.session.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 - - -- draft updated - local supporter - - if app.session.member_id then - supporter = app.session.member:get_reference_selector("supporters") - :add_where{ "initiative_id = ?", initiative.id } - :optional_object_mode() - :exec() - end - - if supporter and not initiative.issue.closed then - local old_draft_id = supporter.draft_id - local new_draft_id = initiative.current_draft.id - if old_draft_id ~= new_draft_id then - ui.container{ - attr = { class = "draft_updated_info" }, - content = function() - slot.put(_"The draft of this initiative has been updated!") - slot.put(" ") - ui.link{ - content = _"Show diff", - module = "draft", - view = "diff", - params = { - old_draft_id = old_draft_id, - new_draft_id = new_draft_id - } - } - if not initiative.revoked then - slot.put(" ") - ui.link{ - text = _"Refresh support to current draft", - module = "initiative", - action = "add_support", - id = initiative.id, - routing = { - default = { - mode = "redirect", - module = "initiative", - view = "show", - id = initiative.id - } - } - } - end - end - } - end - end - - if not show_as_head then - local drafts_count = initiative:get_reference_selector("drafts"):count() - - ui.container{ attr = { class = "content" }, content = function() - - if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then - ui.link{ - content = function() - slot.put(_"Edit draft") - end, - module = "draft", - view = "new", - params = { initiative_id = initiative.id } - } - slot.put(" · ") - ui.link{ - content = function() - slot.put(_"Revoke initiative") - end, - module = "initiative", - view = "revoke", - id = initiative.id - } - slot.put(" · ") - end - - ui.tag{ - attr = { class = "draft_version" }, - content = _("Latest draft created at #{date} #{time}", { - date = format.date(initiative.current_draft.created), - time = format.time(initiative.current_draft.created) - }) - } - if drafts_count > 1 then - slot.put(" · ") - ui.link{ - module = "draft", view = "list", params = { initiative_id = initiative.id }, - text = _("List all revisions (#{count})", { count = drafts_count }) - } - end - end } - - execute.view{ - module = "draft", - view = "_show", - params = { - draft = initiative.current_draft - } - } - end -end } - -if not show_as_head then - execute.view{ - module = "suggestion", - view = "_list", - params = { - initiative = initiative, - suggestions_selector = initiative:get_reference_selector("suggestions"), - tab_id = param.get("tab_id") - } - } - - - if app.session:has_access("all_pseudonymous") then - if initiative.issue.fully_frozen and initiative.issue.closed then - local members_selector = initiative.issue:get_reference_selector("direct_voters") - :left_join("vote", nil, { "vote.initiative_id = ? AND vote.member_id = member.id", initiative.id }) - :add_field("direct_voter.weight as voter_weight") - :add_field("coalesce(vote.grade, 0) as grade") - :add_field("direct_voter.comment as voter_comment") - :left_join("initiative", nil, "initiative.id = vote.initiative_id") - :left_join("issue", nil, "issue.id = initiative.issue_id") - - ui.anchor{ name = "voter", attr = { class = "heading" }, content = _"Voters" } - - execute.view{ - module = "member", - view = "_list", - params = { - initiative = initiative, - for_votes = true, - members_selector = members_selector, - paginator_name = "voter" - } - } - end - - local members_selector = initiative:get_reference_selector("supporting_members_snapshot") - :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id") - :join("direct_interest_snapshot", nil, "direct_interest_snapshot.event = issue.latest_snapshot_event AND direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.member_id = member.id") - :add_field("direct_interest_snapshot.weight") - :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event") - :add_where("direct_supporter_snapshot.satisfied") - :add_field("direct_supporter_snapshot.informed", "is_informed") - - if members_selector:count() > 0 then - if issue.fully_frozen then - ui.anchor{ name = "supporters", attr = { class = "heading" }, content = _"Supporters (before begin of voting)" } - else - ui.anchor{ name = "supporters", attr = { class = "heading" }, content = _"Supporters" } - end - - execute.view{ - module = "member", - view = "_list", - params = { - initiative = initiative, - members_selector = members_selector, - paginator_name = "supporters" - } - } - else - if issue.fully_frozen then - ui.anchor{ name = "supporters", attr = { class = "heading" }, content = _"No supporters (before begin of voting)" } - else - ui.anchor{ name = "supporters", attr = { class = "heading" }, content = _"No supporters" } - end - slot.put("
") - end - - local members_selector = initiative:get_reference_selector("supporting_members_snapshot") - :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id") - :join("direct_interest_snapshot", nil, "direct_interest_snapshot.event = issue.latest_snapshot_event AND direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.member_id = member.id") - :add_field("direct_interest_snapshot.weight") - :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event") - :add_where("NOT direct_supporter_snapshot.satisfied") - :add_field("direct_supporter_snapshot.informed", "is_informed") - - if members_selector:count() > 0 then - if issue.fully_frozen then - ui.anchor{ name = "potential_supporters", attr = { class = "heading" }, content = _"Potential supporters (before begin of voting)" } - else - ui.anchor{ name = "potential_supporters", attr = { class = "heading" }, content = _"Potential supporters" } - end - - execute.view{ - module = "member", - view = "_list", - params = { - initiative = initiative, - members_selector = members_selector, - paginator_name = "potential_supporters" - } - } - else - if issue.fully_frozen then - ui.anchor{ name = "potential_supporters", attr = { class = "heading" }, content = _"No potential supporters (before begin of voting)" } - else - ui.anchor{ name = "potential_supporters", attr = { class = "heading" }, content = _"No potential supporters" } - end - slot.put("
") - end - - ui.container{ attr = { class = "heading" }, content = _"Details" } - execute.view { - module = "initiative", - view = "_details", - params = { - initiative = initiative, - members_selector = members_selector - } - } - - end -end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_sidebar_history.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_sidebar_history.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,14 @@ +local initiative = param.get("initiative", "table") + + +ui.sidebar( function () + ui.sidebarHead( function () + ui.link { attr = { name = "history" }, text = "" } + ui.heading { level = 1, content = _"History" } + end ) + execute.view { + module = "issue", view = "_list2", params = { + for_initiative = initiative, for_sidebar = true + } + } +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_sidebar_policies.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_sidebar_policies.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,10 @@ +local area = param.get("area", "table") + +ui.sidebar ( "tab-whatcanido", function () + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Available policies" } + end ) + execute.view { module = "policy", view = "_list", params = { + for_area = area + } } +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_sidebar_state.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_sidebar_state.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,111 @@ +local initiative = param.get("initiative", "table") + + +-- voting results +if initiative.issue.fully_frozen and initiative.issue.closed and initiative.admitted + and initiative.issue.voter_count then + local class = initiative.winner and "sectionRow admitted_info" or "sectionRow not_admitted_info" + ui.container{ + attr = { class = class }, + content = function() + local max_value = initiative.issue.voter_count + local positive_votes = initiative.positive_votes + local negative_votes = initiative.negative_votes + local abstention_votes = max_value - + negative_votes - + positive_votes + local function perc(votes, sum) + if sum > 0 then return string.format( "%.f", votes * 100 / sum ) .. "%" end + return "" + end + local head_text + if initiative.winner then + head_text = _"Approved" + elseif initiative.rank then + head_text = _("Rejected (rank #{rank})", { rank = initiative.rank }) + else + head_text = _"Rejected" + end + + util.initiative_pie( initiative ) + + ui.heading { level = 1, content = head_text } + + ui.tag { tag = "table", content = function () + ui.tag { tag = "tr", attr = { class = "yes" }, content = function () + ui.tag { tag = "td", content = + tostring(positive_votes) + } + ui.tag { tag = "th", content = _"Yes" } + ui.tag { tag = "td", content = + perc(positive_votes, max_value) + } + ui.tag { tag = "th", content = _"Yes" } + end } + ui.tag { tag = "tr", attr = { class = "abstention" }, content = function () + ui.tag { tag = "td", content = + tostring(abstention_votes) + } + ui.tag { tag = "th", content = _"Abstention" } + ui.tag { tag = "td", content = + perc(abstention_votes, max_value) + } + ui.tag { tag = "th", content = _"Abstention" } + end } + ui.tag { tag = "tr", attr = { class = "no" }, content = function () + ui.tag { tag = "td", content = + tostring(negative_votes) + } + ui.tag { tag = "th", content = _"No" } + ui.tag { tag = "td", content = + perc(negative_votes, max_value) + } + ui.tag { tag = "th", content = _"No" } + end } + end } + end + } +end + +-- initiative not admitted info +if initiative.admitted == false then + local policy = initiative.issue.policy + ui.container{ + attr = { class = "sectionRow not_admitted_info" }, + content = function () + ui.heading { level = 1, content = _"Initiative not admitted" } + ui.container { content = _("This initiative has not been admitted! It failed the 2nd quorum of #{quorum}.", { quorum = format.percentage ( policy.initiative_quorum_num / policy.initiative_quorum_den ) } ) } + end + } +end + +-- initiative revoked info +if initiative.revoked then + ui.container{ + attr = { class = "sectionRow revoked_info" }, + content = function() + ui.heading { level = 1, content = _"Initiative revoked" } + slot.put(_("This initiative has been revoked at #{revoked} by:", { + revoked = format.timestamp(initiative.revoked) + })) + slot.put(" ") + ui.link{ + module = "member", view = "show", id = initiative.revoked_by_member_id, + content = initiative.revoked_by_member.name + } + local suggested_initiative = initiative.suggested_initiative + if suggested_initiative then + slot.put("

") + slot.put(_("The initiators suggest to support the following initiative:")) + slot.put("
") + ui.link{ + content = suggested_initiative.display_name, + module = "initiative", + view = "show", + id = suggested_initiative.id + } + end + end + } +end + \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_sidebar_support.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_sidebar_support.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,108 @@ +if not app.session.member then + return +end + +local initiative = param.get("initiative", "table") + +local initiative_info = initiative.member_info +local issue_info = initiative.issue.member_info + +local active_trustee_id +if not issue_info.own_participation then + if issue_info.first_trustee_participation then + active_trustee_id = issue_info.first_trustee_id + elseif issue_info.other_trustee_participation then + active_trustee_id = issue_info.other_trustee_id + end +end + + +slot.select ( "sidebar", function () + + if + not initiative.issue.fully_frozen + and not initiative.issue.closed + and (issue_info.own_participation or active_trustee_id) + then + ui.container { + attr = { class = "tab-whatcanido sidebarSection" }, + content = function () + + + if initiative_info.supported then + ui.heading { level = 1, content = function () + ui.tag { content = _"I'm supporting this initiative" } + if issue_info.weight then + slot.put ( " " ) + ui.link { + module = "delegation", view = "show_incoming", params = { + issue_id = initiative.issue_id, + member_id = app.session.member_id + }, + content = "+" .. issue_info.weight + } + end + end } + + else + ui.heading { level = 1, content = function () + ui.tag { content = _"I'm interested in this issue" } + if issue_info.weight then + slot.put ( " " ) + ui.link { + module = "delegation", view = "show_incoming", params = { + issue_id = initiative.issue_id, + member_id = app.session.member_id + }, + content = "+" .. issue_info.weight + } + end + end } + end + + if active_trustee_id then + ui.tag { content = _"via delegation" } + elseif issue_info.first_trustee_id then + ui.tag { content = _"delegation suspended during discussion" } + end + end + } + end + + if + initiative.issue.fully_frozen and + (issue_info.direct_voted or active_trustee_id) + then + ui.container { + attr = { class = "tab-whatcanido sidebarSection" }, + content = function () + + if issue_info.direct_voted then + ui.heading { level = 1, content = _"You have been voted" } + ui.link { + content = _"Show my voting ballot", + module = "vote", view = "list", params = { + issue_id = initiative.issue.id + } + } + else + + + if active_trustee_id then + ui.heading { level = 1, content = _"You have been voted" } + ui.container { + content = _"via delegation" + } + ui.link { + content = _"Show voting ballot", + module = "vote", view = "list", params = { + issue_id = initiative.issue.id, member_id = active_trustee_id + } + } + end + end + end + } + end +end ) + \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/_sidebar_wikisyntax.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_sidebar_wikisyntax.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,61 @@ +if config.enforce_formatting_engine ~= 'markdown2' then + return +end + +ui.sidebar( "tab-whatcanido", function() + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Formatting help" } + end ) + ui.sidebarSection( function () + ui.heading { level = 3, content = _"Paragraphs" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = _"Separate each paragraph with at least one blank line" } + end } + end } + + ui.heading { level = 3, content = _"Headlines" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = _"Underline main headlines with ===" } + end } + ui.tag { tag = "li", content = function () + ui.tag { content = _"Underline sub headlines with ---" } + end } + end } + + ui.heading { level = 3, content = _"Emphasis" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = _"Put *asterisks* or around a phrase to make it italic" } + end } + ui.tag { tag = "li", content = function () + ui.tag { content = _"Put **double asterisks** around a phrase to make it bold" } + end } + end } + + ui.heading { level = 3, content = _"Lists" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = _"Lists must be preceeded and followed by at least one blank line" } + end } + ui.tag { tag = "li", content = function () + ui.tag { content = _"Put a hypen (-) or asterisk (*) followed by a space in front of each item" } + end } + ui.tag { tag = "li", content = function () + ui.tag { content = _"For numbered items use a digit (e.g. 1) followed by a dot (.) and a space" } + end } + ui.tag { tag = "li", content = function () + ui.tag { content = _"Indent sub items with spaces" } + end } + end } + + ui.heading { level = 3, content = _"Links" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = _"Use [Text](http://example.com/) for links" } + end } + end } + + end ) +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/add_initiator.lua --- a/app/main/initiative/add_initiator.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/add_initiator.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,26 +1,55 @@ local initiative = Initiative:by_id(param.get("initiative_id")) -slot.put_into("title", _"Invite an initiator to initiative") +local member = app.session.member +if member then + initiative:load_everything_for_member_id(member.id) + initiative.issue:load_everything_for_member_id(member.id) +end + + +local records = { + { + id = "-1", + name = _"Choose member" + } +} +local contact_members = app.session.member:get_reference_selector("saved_members"):add_order_by("name"):exec() +for i, record in ipairs(contact_members) do + records[#records+1] = record +end -slot.select("actions", function() - ui.link{ - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - module = "initiative", - view = "show", - id = initiative.id, - params = { - tab = "initiators" - } +execute.view { + module = "issue", view = "_head", params = { + issue = initiative.issue, + member = app.session.member } -end) +} + +execute.view{ module = "issue", view = "_sidebar_state", params = { + initiative = initiative +} } -util.help("initiative.add_initiator", _"Invite an initiator to initiative") +execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = initiative.issue, + highlight_initiative_id = initiative.id + } +} + +execute.view { + module = "issue", view = "_sidebar_whatcanido", + params = { initiative = initiative } +} + +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = initiative.issue, initiative = initiative + } +} ui.form{ - attr = { class = "vertical" }, + attr = { class = "wide section" }, module = "initiative", action = "add_initiator", params = { @@ -38,23 +67,50 @@ } }, content = function() - local records = { - { - id = "-1", - name = _"Choose member" + + ui.sectionHead( function() + ui.link{ + module = "initiative", view = "show", id = initiative.id, + content = function () + ui.heading { + level = 1, + content = initiative.display_name + } + end + } + ui.heading { level = 2, content = _"Invite an initiator to initiative" } + end ) + + ui.sectionRow( function() + ui.heading { level = 2, content = _"Choose a member to invite" } + ui.field.select{ + name = "member_id", + foreign_records = records, + foreign_id = "id", + foreign_name = "name" } - } - local contact_members = app.session.member:get_reference_selector("saved_members"):add_order_by("name"):exec() - for i, record in ipairs(contact_members) do - records[#records+1] = record - end - ui.field.select{ - label = _"Member", - name = "member_id", - foreign_records = records, - foreign_id = "id", - foreign_name = "name" - } - ui.submit{ text = _"Save" } + ui.container{ content = _"You can choose only members which you have been saved as contact before." } + slot.put("
") + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Invite member" + }, + content = "" + } + slot.put("
") + slot.put("
") + ui.link{ + content = _"Cancel", + module = "initiative", + view = "show", + id = initiative.id, + params = { + tab = "initiators" + } + } + end ) end } \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/history.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/history.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,117 @@ +local initiative = Initiative:by_id(param.get_id()) + +initiative:load_everything_for_member_id(app.session.member_id) +initiative.issue:load_everything_for_member_id(app.session.member_id) + + +execute.view{ module = "issue", view = "_sidebar_state", params = { + initiative = initiative +} } + +execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = initiative.issue, + highlight_initiative_id = initiative.id + } +} + +execute.view { + module = "issue", view = "_sidebar_whatcanido", + params = { initiative = initiative } +} + +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = initiative.issue, initiative = initiative + } +} + + + +execute.view { + module = "issue", view = "_head", params = { + issue = initiative.issue + } +} + +ui.form{ + method = "get", + module = "draft", + view = "diff", + attr = { class = "section" }, + content = function() + ui.field.hidden{ name = "initiative_id", value = initiative.id } + + ui.sectionHead( function() + ui.link{ + module = "initiative", view = "show", id = initiative.id, + content = function () + ui.heading { + level = 1, + content = initiative.display_name + } + end + } + ui.heading { level = 2, content = _"Draft history" } + end) + + ui.sectionRow( function() + + local columns = { + { + label = _"draft ID", + content = function(record) + ui.tag { content = record.id } + end + }, + { + label = _"published at", + content = function(record) + ui.link{ + attr = { class = "action" }, + module = "draft", view = "show", id = record.id, + text = format.timestamp(record.created) + } + end + }, + { + label = _"compare", + content = function(record) + slot.put('') + slot.put('') + end + } + } + + if app.session:has_access("authors_pseudonymous") then + columns[#columns+1] = { + label = _"author", + content = function(record) + if record.author then + return util.micro_avatar ( record.author ) + end + end + } + end + + ui.list{ + records = initiative.drafts, + columns = columns + } + + slot.put("
") + ui.container { attr = { class = "actions" }, content = function() + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"compare revisions" + }, + content = "" + } + end } + end ) + end +} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/new.lua --- a/app/main/initiative/new.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/new.lua Thu Jul 10 01:19:48 2014 +0200 @@ -4,11 +4,13 @@ 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() + issue:load_everything_for_member_id(app.session.member_id) 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() + area:load_delegation_info_once_for_member_id(app.session.member_id) end local polling = param.get("polling", atom.boolean) @@ -16,17 +18,49 @@ local policy_id = param.get("policy_id", atom.integer) local policy +local preview = param.get("preview") + +if #(slot.get_content("error")) > 0 then + preview = false +end + if policy_id then policy = Policy:by_id(policy_id) end if issue_id then - ui.title(_"Add alternative initiative to issue") + execute.view { + module = "issue", view = "_head", + params = { issue = issue, member = app.session.member } + } + execute.view { + module = "issue", view = "_sidebar_state", + params = { + issue = issue + } + } + execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = issue + } + } else - ui.title(_"Create new issue") + execute.view { + module = "area", view = "_head", + params = { area = area, member = app.session.member } + } + execute.view { + module = "initiative", view = "_sidebar_policies", + params = { + area = area, + } + } end -local preview = param.get("preview") + + + if not preview and not issue_id and app.session.member:has_polling_right_for_unit_id(area.unit_id) then ui.actions(function() @@ -59,181 +93,214 @@ }, attr = { class = "vertical" }, content = function() - ui.field.text{ label = _"Unit", value = area.unit.name } - ui.field.text{ label = _"Area", value = area.name } - slot.put("
") - if issue_id then - ui.field.text{ label = _"Issue", value = issue_id } - elseif policy then - ui.field.hidden{ name = "policy_id", value = policy.id } - ui.field.text{ label = _"Policy", value = policy.name } - if policy.free_timeable then - local available_timings - if config.free_timing and config.free_timing.available_func then - available_timings = config.free_timing.available_func(policy) - if available_timings == false then - error("error in free timing config") + + if preview then + ui.section( function() + ui.sectionHead( function() + ui.heading{ level = 1, content = encode.html(param.get("name")) } + if not issue then + ui.container { content = policy.name } end - end - if available_timings then - ui.field.select{ - label = _"Free timing", - name = "free_timing", - foreign_records = available_timings, - foreign_id = "id", - foreign_name = "name", - value = param.get("free_timing") - } - else - ui.field.text{ label = _"Free timing", name = "free_timing", value = param.get("free_timing") } - end - end - else - tmp = { { id = -1, name = _"Please choose a policy" } } - for i, allowed_policy in ipairs(area.allowed_policies) do - if not allowed_policy.polling then - tmp[#tmp+1] = allowed_policy - end - end - ui.field.select{ - label = _"Policy", - name = "policy_id", - foreign_records = tmp, - foreign_id = "id", - foreign_name = "name", - value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id - } - ui.tag{ - tag = "div", - content = function() - ui.tag{ - tag = "label", - attr = { class = "ui_field_label" }, - content = function() slot.put(" ") end, - } - ui.tag{ + slot.put("
") + + ui.field.hidden{ name = "formatting_engine", value = param.get("formatting_engine") } + ui.field.hidden{ name = "policy_id", value = param.get("policy_id") } + ui.field.hidden{ name = "name", value = param.get("name") } + ui.field.hidden{ name = "draft", value = param.get("draft") } + local formatting_engine + if config.enforce_formatting_engine then + formatting_engine = config.enforce_formatting_engine + else + formatting_engine = param.get("formatting_engine") + end + ui.container{ + attr = { class = "draft_content wiki" }, content = function() - ui.link{ - text = _"Information about the available policies", - module = "policy", - view = "list" - } - slot.put(" ") - ui.link{ - attr = { target = "_blank" }, - text = _"(new window)", - module = "policy", - view = "list" - } + slot.put(format.wiki_text(param.get("draft"), formatting_engine)) end } - end - } - end - - if issue and issue.policy.polling and app.session.member:has_polling_right_for_unit_id(area.unit_id) then - ui.field.boolean{ name = "polling", label = _"No admission needed", value = polling } - end - - if preview then - ui.heading{ level = 1, content = encode.html(param.get("name")) } - local discussion_url = param.get("discussion_url") - ui.container{ - attr = { class = "ui_field_label" }, - content = _"Discussion with initiators" - } - ui.tag{ - tag = "span", - content = function() - if discussion_url:find("^https?://") then - if discussion_url and #discussion_url > 0 then - ui.link{ - attr = { - class = "actions", - target = "_blank", - title = discussion_url - }, - content = discussion_url, - external = discussion_url - } - end + slot.put("
") + + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _'Publish now' + }, + content = "" + } + slot.put("
") + slot.put("
") + ui.tag{ + tag = "input", + attr = { + type = "submit", + name = "edit", + class = "btn-link", + value = _'Edit again' + }, + content = "" + } + slot.put(" | ") + if issue then + ui.link{ content = _"Cancel", module = "issue", view = "show", id = issue.id } else - slot.put(encode.html(discussion_url)) + ui.link{ content = _"Cancel", module = "area", view = "show", id = area.id } end - end - } - ui.container{ - attr = { class = "draft_content wiki" }, - content = function() - slot.put(format.wiki_text(param.get("draft"), param.get("formatting_engine"))) - end - } - slot.put("
") - ui.submit{ text = _"Save" } - slot.put("
") - slot.put("
") - end - slot.put("
") + end ) + end ) + else + + + execute.view{ module = "initiative", view = "_sidebar_wikisyntax" } - ui.field.text{ - label = _"Title of initiative", - name = "name", - value = param.get("name") - } - ui.field.text{ - label = _"Discussion URL", - name = "discussion_url", - value = param.get("discussion_url") - } - ui.field.select{ - label = _"Wiki engine", - name = "formatting_engine", - foreign_records = { - { id = "rocketwiki", name = "RocketWiki" }, - { id = "compat", name = _"Traditional wiki syntax" } - }, - attr = {id = "formatting_engine"}, - foreign_id = "id", - foreign_name = "name", - value = param.get("formatting_engine") - } - ui.tag{ - tag = "div", - content = function() - ui.tag{ - tag = "label", - attr = { class = "ui_field_label" }, - content = function() slot.put(" ") end, + ui.section( function() + if preview then + ui.sectionHead( function() + ui.heading { level = 1, content = _"Edit again" } + end ) + elseif issue_id then + ui.sectionHead( function() + ui.heading { level = 1, content = _"Add a new competing initiative to issue" } + end ) + else + ui.sectionHead( function() + ui.heading { level = 1, content = _"Create a new issue" } + end ) + end + + ui.sectionRow( function() + if not preview and not issue_id then + ui.container { attr = { class = "section" }, content = _"Before creating a new issue, please check any existant issues before, if the topic is already in discussion." } + slot.put("
") + end + if not issue_id then + tmp = { { id = -1, name = "" } } + for i, allowed_policy in ipairs(area.allowed_policies) do + if not allowed_policy.polling then + tmp[#tmp+1] = allowed_policy + end + end + ui.heading{ level = 2, content = _"Please choose a policy for the new issue:" } + ui.field.select{ + name = "policy_id", + foreign_records = tmp, + foreign_id = "id", + foreign_name = "name", + value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id + } + if policy and policy.free_timeable then + ui.sectionRow( function() + local available_timings + if config.free_timing and config.free_timing.available_func then + available_timings = config.free_timing.available_func(policy) + if available_timings == false then + error("error in free timing config") + end + end + ui.heading{ level = 4, content = _"Free timing:" } + if available_timings then + ui.field.select{ + name = "free_timing", + foreign_records = available_timings, + foreign_id = "id", + foreign_name = "name", + value = param.get("free_timing") + } + else + ui.field.text{ + name = "free_timing", + value = param.get("free_timing") + } + end + end ) + end + end + + if issue and issue.policy.polling and app.session.member:has_polling_right_for_unit_id(area.unit_id) then + slot.put("
") + ui.field.boolean{ name = "polling", label = _"No admission needed", value = polling } + end + + slot.put("
") + ui.heading { level = 2, content = _"Enter a title for your initiative (max. 140 chars):" } + ui.field.text{ + attr = { style = "width: 100%;" }, + name = "name", + value = param.get("name") } + ui.container { content = _"The title is the figurehead of your iniative. It should be short but meaningful! As others identifies your initiative by this title, you cannot change it later!" } + + if not config.enforce_formatting_engine then + slot.put("
") + ui.heading { level = 4, content = _"Choose a formatting engine:" } + ui.field.select{ + name = "formatting_engine", + foreign_records = config.formatting_engines, + attr = {id = "formatting_engine"}, + foreign_id = "id", + foreign_name = "name", + value = param.get("formatting_engine") + } + end + slot.put("
") + + ui.heading { level = 2, content = _"Enter your proposal and/or reasons:" } + ui.field.text{ + name = "draft", + multiline = true, + attr = { style = "height: 50ex; width: 100%;" }, + value = param.get("draft") or + [[ +Proposal +====== + +Replace me with your proposal. + + +Reasons +====== + +Argument 1 +------ + +Replace me with your first argument + + +Argument 2 +------ + +Replace me with your second argument + +]] + } + if not issue or issue.state == "admission" or issue.state == "discussion" then + ui.container { content = _"You can change your text again anytime during admission and discussion phase" } + else + ui.container { content = _"You cannot change your text again later, because this issue is already in verfication phase!" } + end + slot.put("
") ui.tag{ - content = function() - ui.link{ - text = _"Syntax help", - module = "help", - view = "show", - id = "wikisyntax", - attr = {onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} - } - slot.put(" ") - ui.link{ - text = _"(new window)", - module = "help", - view = "show", - id = "wikisyntax", - attr = {target = "_blank", onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} - } - end + tag = "input", + attr = { + type = "submit", + name = "preview", + class = "btn btn-default", + value = _'Preview' + }, + content = "" } - end - } - ui.field.text{ - label = _"Draft", - name = "draft", - multiline = true, - attr = { style = "height: 50ex;" }, - value = param.get("draft") - } - ui.submit{ name = "preview", text = _"Preview" } - ui.submit{ text = _"Save" } + slot.put("
") + slot.put("
") + + if issue then + ui.link{ content = _"Cancel", module = "issue", view = "show", id = issue.id } + else + ui.link{ content = _"Cancel", module = "area", view = "show", id = area.id } + end + end ) + end ) + end end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/remove_initiator.lua --- a/app/main/initiative/remove_initiator.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/remove_initiator.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,31 +1,48 @@ local initiative = Initiative:by_id(param.get("initiative_id")) +local member = app.session.member +if member then + initiative:load_everything_for_member_id(member.id) + initiative.issue:load_everything_for_member_id(member.id) +end + local initiator = Initiator:by_pk(initiative.id, app.session.member.id) if not initiator or initiator.accepted ~= true then error("access denied") end -slot.put_into("title", _"Remove initiator from initiative") +execute.view { + module = "issue", view = "_head", params = { + issue = initiative.issue, + member = app.session.member + } +} + +execute.view{ module = "issue", view = "_sidebar_state", params = { + initiative = initiative +} } -slot.select("actions", function() - ui.link{ - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - module = "initiative", - view = "show", - id = initiative.id, - params = { - tab = "initiators" - } +execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = initiative.issue, + highlight_initiative_id = initiative.id } -end) +} -util.help("initiative.remove_initiator", _"Remove initiator from initiative") +execute.view { + module = "issue", view = "_sidebar_whatcanido", + params = { initiative = initiative } +} + +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = initiative.issue, initiative = initiative + } +} ui.form{ - attr = { class = "vertical" }, + attr = { class = "vertical section" }, module = "initiative", action = "remove_initiator", params = { @@ -43,23 +60,50 @@ } }, content = function() - local records = { - { - id = "-1", - name = _"Choose initiator" + + ui.sectionHead( function() + ui.link{ + module = "initiative", view = "show", id = initiative.id, + content = function () + ui.heading { + level = 1, + content = initiative.display_name + } + end + } + ui.heading { level = 2, content = _"Remove an initiator from initiative" } + end ) + + ui.sectionRow( function() + local records = initiative:get_reference_selector("initiating_members"):add_where("accepted OR accepted ISNULL"):exec() + ui.heading{ level = 2, content = _"Choose an initiator to remove" } + ui.field.select{ + name = "member_id", + foreign_records = records, + foreign_id = "id", + foreign_name = "name", } - } - local members = initiative:get_reference_selector("initiating_members"):add_where("accepted OR accepted ISNULL"):exec() - for i, record in ipairs(members) do - records[#records+1] = record - end - ui.field.select{ - label = _"Member", - name = "member_id", - foreign_records = records, - foreign_id = "id", - foreign_name = "name" - } - ui.submit{ text = _"Save" } + slot.put("
") + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-dangerous", + value = _"Remove initiator" + }, + content = "" + } + slot.put("
") + slot.put("
") + ui.link{ + content = _"Cancel", + module = "initiative", + view = "show", + id = initiative.id, + params = { + tab = "initiators" + } + } + end ) end } \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/revoke.lua --- a/app/main/initiative/revoke.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/revoke.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,26 +1,60 @@ local initiative = Initiative:by_id(param.get_id()) +local initiatives = app.session.member + :get_reference_selector("supported_initiatives") + :join("issue", nil, "issue.id = initiative.issue_id") + :add_where("issue.closed ISNULL") + :add_order_by("issue.id") + :exec() -slot.put_into("title", _"Revoke initiative") + +local member = app.session.member +if member then + initiative:load_everything_for_member_id(member.id) + initiative.issue:load_everything_for_member_id(member.id) +end + + +local tmp = { { id = -1, myname = _"Suggest no initiative" }} +for i, initiative in ipairs(initiatives) do + initiative.myname = _("Issue ##{issue_id}: #{initiative_name}", { + issue_id = initiative.issue.id, + initiative_name = initiative.name + }) + tmp[#tmp+1] = initiative +end -slot.select("actions", function() - ui.link{ - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - module = "initiative", - view = "show", - id = initiative.id, - params = { - tab = "initiators" - } +execute.view { + module = "issue", view = "_head", params = { + issue = initiative.issue, + member = member } -end) +} +execute.view{ module = "issue", view = "_sidebar_state", params = { + initiative = initiative +} } -util.help("initiative.revoke") +execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = initiative.issue, + highlight_initiative_id = initiative.id + } +} + +execute.view { + module = "issue", view = "_sidebar_whatcanido", + params = { initiative = initiative } +} + +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = initiative.issue, initiative = initiative + } +} + ui.form{ - attr = { class = "vertical" }, + attr = { class = "wide section" }, module = "initiative", action = "revoke", id = initiative.id, @@ -33,30 +67,67 @@ } }, content = function() - local initiatives = app.session.member - :get_reference_selector("supported_initiatives") - :join("issue", nil, "issue.id = initiative.issue_id") - :add_field("'Issue #' || issue.id || ': ' || initiative.name", "myname") - :exec() + + ui.sectionHead( function() + ui.link{ + module = "initiative", view = "show", id = initiative.id, + content = function () + ui.heading { + level = 1, + content = initiative.display_name + } + end + } + ui.heading { level = 2, content = _"Revoke initiative" } + end ) + + ui.sectionRow( function() - local tmp = { { id = -1, myname = _"Suggest no initiative" }} - for i, initiative in ipairs(initiatives) do - tmp[#tmp+1] = initiative - end - ui.field.select{ - label = _"Suggested initiative", - name = "suggested_initiative_id", - foreign_records = tmp, - foreign_id = "id", - foreign_name = "myname", - value = param.get("suggested_initiative_id", atom.integer) - } - slot.put("") - ui.field.boolean{ - label = _"Are you sure?", - name = "are_you_sure", - } + ui.heading{ level = 2, content = _"Do you want to suggest to support another initiative?" } + + ui.field.select{ + name = "suggested_initiative_id", + foreign_records = tmp, + foreign_id = "id", + foreign_name = "myname", + value = param.get("suggested_initiative_id", atom.integer) + } + ui.container{ content = _"You may choose one of the ongoing initiatives you are currently supporting" } + slot.put("
") + ui.heading { level = 2, content = _"Are you aware that revoking an initiative is irrevocable?" } + ui.container{ content = function() + ui.tag{ tag = "input", attr = { + type = "checkbox", + name = "are_you_sure", + value = "1" + } } + ui.tag { content = _"I understand, that this is not revocable" } + end } + + + slot.put("
") + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-dangerous", + value = _"Revoke now" + }, + content = "" + } + slot.put("
") + slot.put("
") - ui.submit{ text = _"Revoke initiative" } + ui.link{ + content = _"Cancel", + module = "initiative", + view = "show", + id = initiative.id, + params = { + tab = "initiators" + } + } + end ) + end } \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/initiative/show.lua --- a/app/main/initiative/show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/initiative/show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,7 +1,541 @@ -local initiative = Initiative:by_id(param.get_id()) +local initiative = Initiative:by_id ( param.get_id() ) +local member = app.session.member + +if not initiative then + execute.view { module = "index", view = "404" } + request.set_status("404 Not Found") + return +end + +local issue_info + +if member then + initiative:load_everything_for_member_id(member.id) + initiative.issue:load_everything_for_member_id(member.id) + issue_info = initiative.issue.member_info +end + +execute.view { + module = "issue", view = "_head", + params = { + issue = initiative.issue, + initiative = initiative, + member = app.session.member + } +} + +if app.session.member_id then + direct_supporter = initiative.issue.member_info.own_participation and initiative.member_info.supported +end -execute.view{ - module = "initiative", view = "_show", params = { - initiative = initiative +ui.script { script = [[ + function showTab(tabId) { + $('.tab').hide(); + $('.main').hide(); + $('.main, .slot_extra .section').hide(); + $('.' + tabId).show(); + if (tabId == "main") $('.slot_extra .section').show(); + }; + showTab('main'); +]]} + +execute.view{ module = "issue", view = "_sidebar_state", params = { + initiative = initiative +} } + +execute.view { + module = "issue", view = "_sidebar_issue", + params = { + issue = initiative.issue, + highlight_initiative_id = initiative.id + } +} + +execute.view { + module = "issue", view = "_sidebar_whatcanido", + params = { initiative = initiative } +} + +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = initiative.issue, initiative = initiative } } + +ui.section( function () + execute.view{ + module = "initiative", view = "_head", params = { + initiative = initiative + } + } + + if direct_supporter and not initiative.issue.closed then + local supporter = app.session.member:get_reference_selector("supporters") + :add_where{ "initiative_id = ?", initiative.id } + :optional_object_mode() + :exec() + + if supporter then + + local old_draft_id = supporter.draft_id + local new_draft_id = initiative.current_draft.id + + if old_draft_id ~= new_draft_id then + ui.sectionRow( "draft_updated_info", function () + ui.container{ + attr = { class = "info" }, + content = _"The draft of this initiative has been updated!" + } + slot.put(" ") + ui.link{ + content = _"show differences", + module = "draft", + view = "diff", + params = { + old_draft_id = old_draft_id, + new_draft_id = new_draft_id + } + } + if not initiative.revoked then + slot.put(" | ") + ui.link{ + text = _"refresh my support", + module = "initiative", + action = "add_support", + id = initiative.id, + params = { draft_id = initiative.current_draft.id }, + routing = { + default = { + mode = "redirect", + module = "initiative", + view = "show", + id = initiative.id + } + } + } + slot.put(" | ") + end + + ui.link{ + text = _"remove my support", + module = "initiative", + action = "remove_support", + id = initiative.id, + routing = { + default = { + mode = "redirect", + module = "initiative", + view = "show", + id = initiative.id + } + } + } + + end ) + end + end + end + + + ui.sectionRow( function () + ui.container { + attr = { class = "draft" }, + content = function () + slot.put ( initiative.current_draft:get_content ( "html" ) ) + end + } + end ) + +end) + +ui.link { attr = { name = "suggestions" }, text = "" } + + +ui.container { + attr = { class = "section suggestions" }, + content = function () + + if # ( initiative.suggestions ) > 0 then + + ui.sectionHead( function () + ui.heading { + level = 1, + content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) + } + ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" } + end ) + + for i, suggestion in ipairs(initiative.suggestions) do + + local opinion = Opinion:by_pk(app.session.member_id, suggestion.id) + + local class = "sectionRow suggestion" + if suggestion.id == param.get("suggestion_id", atom.number) then + class = class .. " highlighted" + end + if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then + class = class .. " rateable" + end + + + ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function () + + if opinion then + + ui.container { attr = { class = "opinion"}, content = function() + local class = "" + local text = "" + + if opinion.degree == 2 then + class = "must" + text = _"must" + elseif opinion.degree == 1 then + class = "should" + text = _"should" + elseif opinion.degree == 0 then + class = "neutral" + text = _"neutral" + elseif opinion.degree == -1 then + class = "shouldnot" + text = _"should not" + elseif opinion.degree == -2 then + class = "mustnot" + text = _"must not" + end + + ui.tag { + attr = { class = class }, + content = text + } + + slot.put ( " " ) + + if + (opinion.degree > 0 and not opinion.fulfilled) + or (opinion.degree < 0 and opinion.fulfilled) + then + ui.tag{ content = _"but" } + else + ui.tag{ content = _"and" } + end + + slot.put ( " " ) + + local class = "" + local text = "" + + if opinion.fulfilled then + class = "implemented" + text = _"is implemented" + else + class = "notimplemented" + text = _"is not implemented" + end + + ui.tag { + attr = { class = class }, + content = text + } + + if + (opinion.degree > 0 and not opinion.fulfilled) + or (opinion.degree < 0 and opinion.fulfilled) + then + if math.abs(opinion.degree) > 1 then + slot.put(" !!") + else + slot.put(" !") + end + else + slot.put(" ✓") + end + + end } + + end + + + ui.link { attr = { name = "s" .. suggestion.id }, text = "" } + ui.heading { level = 2, + attr = { class = "suggestionHead" }, + content = format.string(suggestion.name, { + truncate_at = 160, truncate_suffix = true + }) } + + + local plus2 = (suggestion.plus2_unfulfilled_count or 0) + + (suggestion.plus2_fulfilled_count or 0) + local plus1 = (suggestion.plus1_unfulfilled_count or 0) + + (suggestion.plus1_fulfilled_count or 0) + local minus1 = (suggestion.minus1_unfulfilled_count or 0) + + (suggestion.minus1_fulfilled_count or 0) + local minus2 = (suggestion.minus2_unfulfilled_count or 0) + + (suggestion.minus2_fulfilled_count or 0) + + local with_opinion = plus2 + plus1 + minus1 + minus2 + + local neutral = (suggestion.initiative.supporter_count or 0) + - with_opinion + + local neutral2 = with_opinion + - (suggestion.plus2_fulfilled_count or 0) + - (suggestion.plus1_fulfilled_count or 0) + - (suggestion.minus1_fulfilled_count or 0) + - (suggestion.minus2_fulfilled_count or 0) + + ui.container { + attr = { class = "suggestionInfo" }, + content = function () + + if with_opinion > 0 then + ui.container { attr = { class = "suggestion-rating" }, content = function () + ui.tag { content = _"collective rating:" } + slot.put(" ") + ui.bargraph{ + max_value = suggestion.initiative.supporter_count, + width = 100, + bars = { + { color = "#0a0", value = plus2 }, + { color = "#8a8", value = plus1 }, + { color = "#eee", value = neutral }, + { color = "#a88", value = minus1 }, + { color = "#a00", value = minus2 }, + } + } + slot.put(" | ") + ui.tag { content = _"implemented:" } + slot.put ( " " ) + ui.bargraph{ + max_value = with_opinion, + width = 100, + bars = { + { color = "#0a0", value = suggestion.plus2_fulfilled_count }, + { color = "#8a8", value = suggestion.plus1_fulfilled_count }, + { color = "#eee", value = neutral2 }, + { color = "#a88", value = suggestion.minus1_fulfilled_count }, + { color = "#a00", value = suggestion.minus2_fulfilled_count }, + } + } + end } + end + + if app.session:has_access("authors_pseudonymous") then + util.micro_avatar ( suggestion.author ) + else + slot.put("
") + end + + ui.container { + attr = { class = "suggestion-text" }, + content = function () + slot.put ( suggestion:get_content( "html" ) ) + + if direct_supporter then + + ui.container { + attr = { class = "rating" }, + content = function () + + if not opinion then + opinion = {} + end + ui.form { + module = "opinion", action = "update", params = { + suggestion_id = suggestion.id + }, + routing = { default = { + mode = "redirect", + module = "initiative", view = "show", id = suggestion.initiative_id, + params = { suggestion_id = suggestion.id }, + anchor = "s" .. suggestion.id -- TODO webmcp + } }, + content = function () + + + ui.heading { level = 3, content = _"Should the initiator implement this suggestion?" } + ui.container { content = function () + + local active = opinion.degree == 2 + ui.tag { tag = "input", attr = { + type = "radio", name = "degree", value = 2, + id = "s" .. suggestion.id .. "_degree2", + checked = active and "checked" or nil + } } + ui.tag { + tag = "label", + attr = { + ["for"] = "s" .. suggestion.id .. "_degree2", + class = active and "active-plus2" or nil, + }, + content = _"must" + } + + local active = opinion.degree == 1 + ui.tag { tag = "input", attr = { + type = "radio", name = "degree", value = 1, + id = "s" .. suggestion.id .. "_degree1", + checked = active and "checked" or nil + } } + ui.tag { + tag = "label", + attr = { + ["for"] = "s" .. suggestion.id .. "_degree1", + class = active and "active-plus1" or nil, + }, + content = _"should" + } + + local active = not opinion.member_id + ui.tag { tag = "input", attr = { + type = "radio", name = "degree", value = 0, + id = "s" .. suggestion.id .. "_degree0", + checked = active and "checked" or nil + } } + ui.tag { + tag = "label", + attr = { + ["for"] = "s" .. suggestion.id .. "_degree0", + class = active and "active-neutral" or nil, + }, + content = _"neutral" + } + + local active = opinion.degree == -1 + ui.tag { tag = "input", attr = { + type = "radio", name = "degree", value = -1, + id = "s" .. suggestion.id .. "_degree-1", + checked = active and "checked" or nil + } } + ui.tag { + tag = "label", + attr = { + ["for"] = "s" .. suggestion.id .. "_degree-1", + class = active and "active-minus1" or nil, + }, + content = _"should not" + } + + local active = opinion.degree == -2 + ui.tag { tag = "input", attr = { + type = "radio", name = "degree", value = -2, + id = "s" .. suggestion.id .. "_degree-2", + checked = active and "checked" or nil + } } + ui.tag { + tag = "label", + attr = { + ["for"] = "s" .. suggestion.id .. "_degree-2", + class = active and "active-minus2" or nil, + }, + content = _"must not" + } + end } + + slot.put("
") + + ui.heading { level = 3, content = _"Did the initiator implement this suggestion?" } + ui.container { content = function () + local active = opinion.fulfilled == false + ui.tag { tag = "input", attr = { + type = "radio", name = "fulfilled", value = "false", + id = "s" .. suggestion.id .. "_notfulfilled", + checked = active and "checked" or nil + } } + ui.tag { + tag = "label", + attr = { + ["for"] = "s" .. suggestion.id .. "_notfulfilled", + class = active and "active-notfulfilled" or nil, + }, + content = _"No (not yet)" + } + + local active = opinion.fulfilled + ui.tag { tag = "input", attr = { + type = "radio", name = "fulfilled", value = "true", + id = "s" .. suggestion.id .. "_fulfilled", + checked = active and "checked" or nil + } } + ui.tag { + tag = "label", + attr = { + ["for"] = "s" .. suggestion.id .. "_fulfilled", + class = active and "active-fulfilled" or nil, + }, + content = _"Yes, it's implemented" + } + end } + slot.put("
") + + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"publish my rating" + }, + content = "" + } + + end + } + + end -- if not issue,fully_frozen or closed + } + end + + local text = _"Read more" + + if direct_supporter then + text = _"Show more and rate this" + end + + ui.link { + attr = { + class = "suggestion-more", + onclick = "$('#s" .. suggestion.id .. "').removeClass('folded').addClass('unfolded'); return false;" + }, + text = text + } + + ui.link { + attr = { + class = "suggestion-less", + onclick = "$('#s" .. suggestion.id .. "').addClass('folded').removeClass('unfolded'); return false;" + }, + text = _"Show less" + } + end + } + + ui.script{ script = [[ + var textEl = $('#s]] .. suggestion.id .. [[ .suggestion-text'); + var height = textEl.height(); + if (height > 150) $('#s]] .. suggestion.id .. [[').addClass('folded'); + ]] } + + end + } -- ui.paragraph + + + + end } -- ui.tag "li" + + end -- for i, suggestion + + else -- if #initiative.suggestions > 0 + + local text + if initiative.issue.closed then + text = "No suggestions" + else + text = "No suggestions (yet)" + end + ui.sectionHead( function() + ui.heading { level = 1, content = text } + end) + + end -- if #initiative.suggestions > 0 + + end +} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/interest/_action/update.lua --- a/app/main/interest/_action/update.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/interest/_action/update.lua Thu Jul 10 01:19:48 2014 +0200 @@ -4,6 +4,10 @@ local issue = Issue:new_selector():add_where{ "id = ?", issue_id }:for_share():single_object_mode():exec() +if not app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) then + error("access denied") +end + if issue.closed then slot.put_into("error", _"This issue is already closed.") return false @@ -21,23 +25,17 @@ if param.get("delete", atom.boolean) then if interest then interest:destroy() - --slot.put_into("notice", _"Interest removed") + slot.put_into("notice", _"Interest removed") else - --slot.put_into("notice", _"Interest not existent") + slot.put_into("notice", _"Interest already removed") end return end -if not app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) then - error("access denied") -end - if not interest then interest = Interest:new() interest.issue_id = issue_id interest.member_id = app.session.member_id + interest:save() + slot.put_into("notice", _"Interest updated") end - -interest:save() - ---slot.put_into("notice", _"Interest updated") diff -r a6c7bf07badb -r 701a5cf6b067 app/main/interest/show_incoming.lua --- a/app/main/interest/show_incoming.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/interest/show_incoming.lua Thu Jul 10 01:19:48 2014 +0200 @@ -10,11 +10,25 @@ :add_field{ "delegating_interest_snapshot.weight" } execute.view{ - module = "member", - view = "_list", - params = { - members_selector = members_selector, - issue = issue, - trustee = member + module = "issue", view = "_head", params = { + issue = issue } -} \ No newline at end of file +} + +ui.section( function() + + ui.sectionHead( function() + ui.heading{ level = 1, content = _("Incoming delegations for '#{member}'", { member = member.name }) } + end) + + execute.view{ + module = "member", + view = "_list", + params = { + members_selector = members_selector, + issue = issue, + trustee = member + } + } + +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_details.lua --- a/app/main/issue/_details.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -local issue = param.get("issue", "table") - -local policy = issue.policy -ui.form{ - record = issue, - readonly = true, - attr = { class = "vertical" }, - content = function() - ui.field.text{ label = _"Population", name = "population" } - ui.field.timestamp{ label = _"Created at", name = "created" } - if policy.polling then - ui.field.text{ label = _"Admission time", value = _"Implicitly admitted" } - else - ui.field.text{ label = _"Admission time", value = format.interval_text(issue.admission_time_text) } - ui.field.text{ - label = _"Issue quorum", - value = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den) - } - if issue.population then - ui.field.text{ - label = _"Currently required", - value = math.ceil(issue.population * policy.issue_quorum_num / policy.issue_quorum_den) - } - end - end - if issue.accepted then - ui.field.timestamp{ label = _"Accepted at", name = "accepted" } - end - ui.field.text{ label = _"Discussion time", value = format.interval_text(issue.discussion_time_text) } - if issue.half_frozen then - ui.field.timestamp{ label = _"Half frozen at", name = "half_frozen" } - end - ui.field.text{ label = _"Verification time", value = format.interval_text(issue.verification_time_text) } - ui.field.text{ - label = _"Initiative quorum", - value = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den) - } - if issue.population then - ui.field.text{ - label = _"Currently required", - value = math.ceil(issue.population * (issue.policy.initiative_quorum_num / issue.policy.initiative_quorum_den)), - } - end - if issue.fully_frozen then - ui.field.timestamp{ label = _"Fully frozen at", name = "fully_frozen" } - end - ui.field.text{ label = _"Voting time", value = format.interval_text(issue.voting_time_text) } - if issue.closed then - ui.field.timestamp{ label = _"Closed", name = "closed" } - end - end -} -ui.form{ - record = issue.policy, - readonly = true, - content = function() - end -} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_filters.lua --- a/app/main/issue/_filters.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/issue/_filters.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,386 +1,326 @@ -local member = param.get("member", "table") -local for_member = param.get("for_member", "table") -local state = param.get("state") +local params = param.get_all_cgi() + local for_unit = param.get("for_unit", atom.boolean) local for_area = param.get("for_area", atom.boolean) - local for_events = param.get("for_events", atom.boolean) +local for_member = param.get("for_member", "table") +local member = param.get("member", "table") +local phase = params["phase"] local filters = {} -local filter = { name = "filter" } - -if state ~= "closed" then - filter[#filter+1] = { - name = "any", - label = _"Any phase", - selector_modifier = function(selector) end - } +local admission_order_field = "filter_issue_order.order_in_unit" +if for_area then + admission_order_field = "filter_issue_order.order_in_area" end -if not state then +if not for_issue and not for_member then + + -- mode + + local filter = { class = "filter_mode", name = "mode" } + + filter[#filter+1] = { + name = "issue", + label = _"issue view", + selector_modifier = function () end + } + filter[#filter+1] = { - name = "open", - label = _"Open", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state in ('admission', 'discussion', 'verification', 'voting')") - else - selector:add_where("issue.closed ISNULL") + name = "timeline", + label = _"timeline", + selector_modifier = function ( selector ) + selector:add_order_by ( "event.occurrence DESC" ) + selector:add_order_by ( "id DESC" ) + end + } + + filters[#filters+1] = filter + + -- context + + local filter = { class = "filter_filter", name = "filter" } + + if member and not for_unit and not for_area then + filter[#filter+1] = { + name = "my_units", + label = _"in my units", + selector_modifier = function ( selector ) + selector:join ( "area", "filter_area", "filter_area.id = issue.area_id" ) + selector:join ( "privilege", "filter_privilege", { + "filter_privilege.unit_id = filter_area.unit_id AND filter_privilege.member_id = ?", member.id + }) + end + } + end + + if member and not for_area then + + filter[#filter+1] = { + name = "my_areas", + label = _"in my areas", + selector_modifier = function ( selector ) + selector:join ( "membership", "filter_membership", { + "filter_membership.area_id = issue.area_id AND filter_membership.member_id = ?", member.id + }) + end + } + end + + if member then + filter[#filter+1] = { + name = "my_issues", + label = _"my issues", + selector_modifier = function ( selector ) + selector:left_join("interest", "filter_interest", { "filter_interest.issue_id = issue.id AND filter_interest.member_id = ? ", member.id }) + --selector:left_join("direct_interest_snapshot", "filter_interest_s", { "filter_interest_s.issue_id = issue.id AND filter_interest_s.member_id = ? AND filter_interest_s.event = issue.latest_snapshot_event", member.id }) + selector:left_join("delegating_interest_snapshot", "filter_d_interest_s", { "filter_d_interest_s.issue_id = issue.id AND filter_d_interest_s.member_id = ? AND filter_d_interest_s.event = issue.latest_snapshot_event", member.id }) + end + } + end + + filter[#filter+1] = { + name = "all", + label = _"all issues", + selector_modifier = function() end + } + + filters[#filters+1] = filter + + -- phase + + local filter = { name = "phase" } + + filter[#filter+1] = { + name = "all", + label = _"in all phases", + selector_modifier = function ( selector ) + if not for_events then + selector:left_join ( "issue_order_in_admission_state", "filter_issue_order", "filter_issue_order.id = issue.id" ) + selector:add_order_by ( "issue.closed DESC NULLS FIRST" ) + selector:add_order_by ( "issue.accepted ISNULL" ) + selector:add_order_by ( "CASE WHEN issue.accepted ISNULL THEN NULL ELSE justify_interval(coalesce(issue.fully_frozen + issue.voting_time, issue.half_frozen + issue.verification_time, issue.accepted + issue.discussion_time, issue.created + issue.admission_time) - now()) END" ) + selector:add_order_by ( "CASE WHEN issue.accepted ISNULL THEN " .. admission_order_field .. " ELSE NULL END" ) + selector:add_order_by ( "id" ) end end } -end -if not state or state == "open" then filter[#filter+1] = { - name = "new", - label = _"New", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state = 'admission'") - else - selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL") + name = "admission", + label = _"(1) Admission", + selector_modifier = function ( selector ) + selector:add_where { "issue.state = ?", "admission" } + if not for_events then + selector:left_join ( "issue_order_in_admission_state", "filter_issue_order", "filter_issue_order.id = issue.id" ) + selector:add_order_by ( admission_order_field ) + selector:add_order_by ( "id" ) end end } + filter[#filter+1] = { - name = "accepted", - label = _"Discussion", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state = 'discussion'") - else - selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL") + name = "discussion", + label = _"(2) Discussion", + selector_modifier = function ( selector ) + selector:add_where { "issue.state = ?", "discussion" } + if not for_events then + selector:add_order_by ( "issue.accepted + issue.discussion_time - now()" ) + selector:add_order_by ( "id" ) end end } + filter[#filter+1] = { - name = "half_frozen", - label = _"Frozen", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state = 'verification'") - else - selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL") + name = "verification", + label = _"(3) Verification", + selector_modifier = function ( selector ) + selector:add_where { "issue.state = ?", "verification" } + if not for_events then + selector:add_order_by ( "issue.half_frozen + issue.verification_time - now()" ) + selector:add_order_by ( "id" ) + end + end + } + + filter[#filter+1] = { + name = "voting", + label = _"(4) Voting", + selector_modifier = function ( selector ) + selector:add_where { "issue.state = ?", "voting" } + if not for_events then + selector:add_order_by ( "issue.fully_frozen + issue.voting_time - now()" ) + selector:add_order_by ( "id" ) end end } - filter[#filter+1] = { - name = "frozen", - label = _"Voting", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state = 'voting'") - else - selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL") - end - filter_voting = true - end - } -end -if not state then filter[#filter+1] = { - name = "finished", - label = _"Finished", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state IN ('finished_with_winner', 'finished_without_winner')") - else - selector:add_where("issue.closed NOTNULL AND issue.fully_frozen NOTNULL") - end - end - } - filter[#filter+1] = { - name = "canceled", - label = _"Canceled", - selector_modifier = function(selector) - - if for_events then - selector:add_where("event.state IN ('canceled_revoked_before_accepted', 'canceled_issue_not_accepted', 'canceled_after_revocation_during_discussion', 'canceled_after_revocation_during_verification')") - else - selector:add_where("issue.closed NOTNULL AND issue.fully_frozen ISNULL") + name = "closed", + label = _"(5) Result", + selector_modifier = function ( selector ) + if not for_events then + selector:add_where ( "issue.closed NOTNULL" ) + selector:add_order_by ( "issue.closed DESC" ) + selector:add_order_by ( "id" ) end end } -end + + filters[#filters+1] = filter + + -- my issues + + if params["filter"] == "my_issues" then + + local delegation = params["delegation"] -if state == "closed" then - filter[#filter+1] = { - name = "any", - label = _"Any state", - selector_modifier = function(selector) end - } + local filter = { class = "filter_interest subfilter", name = "interest" } + + filter[#filter+1] = { + name = "all", + label = _"interested directly or via delegation", + selector_modifier = function ( selector ) + selector:add_where ( "filter_interest.issue_id NOTNULL OR filter_d_interest_s.issue_id NOTNULL" ) + end + } + + filter[#filter+1] = { + name = "direct", + label = _"direct interest", + selector_modifier = function ( selector ) + selector:add_where ( "filter_interest.issue_id NOTNULL" ) + end + } - filter[#filter+1] = { - name = "finished", - label = _"Finished", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state IN ('finished_with_winner', 'finished_without_winner')") - else - selector:add_where("issue.state IN ('finished_with_winner', 'finished_without_winner')") + filter[#filter+1] = { + name = "via_delegation", + label = _"interest via delegation", + selector_modifier = function ( selector ) + selector:add_where ( "filter_d_interest_s.issue_id NOTNULL" ) + end + } + + filter[#filter+1] = { + name = "initiated", + label = _"initiated by me", + selector_modifier = function ( selector ) + selector:add_where ( "filter_interest.issue_id NOTNULL" ) end - end - } - filter[#filter+1] = { - name = "finished_with_winner", - label = _"with winner", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state = 'finished_with_winner'") - else - selector:add_where("issue.state = 'finished_with_winner'") + } + + filters[#filters+1] = filter + + end + + -- voting + + if phase == "voting" and member then + + local filter = { class = "subfilter", name = "voted" } + + filter[#filter+1] = { + name = "all", + label = _"voted and not voted by me", + selector_modifier = function(selector) end + } + + filter[#filter+1] = { + name = "voted", + label = _"voted by me", + selector_modifier = function(selector) + selector:join("direct_voter", "filter_direct_voter", { "filter_direct_voter.issue_id = issue.id AND filter_direct_voter.member_id = ?", member.id }) end - end - } - filter[#filter+1] = { - name = "finished_without_winner", - label = _"without winner", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state = 'finished_without_winner'") - else - selector:add_where("issue.state = 'finished_without_winner'") + } + + filter[#filter+1] = { + name = "not_voted", + label = _"not voted by me", + selector_modifier = function(selector) + selector:left_join("direct_voter", "filter_direct_voter", { "filter_direct_voter.issue_id = issue.id AND filter_direct_voter.member_id = ?", member.id }) + selector:add_where("filter_direct_voter.issue_id ISNULL") end - end - } - filter[#filter+1] = { - name = "canceled", - label = _"Canceled", - selector_modifier = function(selector) - if for_events then - selector:add_where("event.state NOT IN ('finished_with_winner', 'finished_without_winner')") - else - selector:add_where("issue.state NOT IN ('finished_with_winner', 'finished_without_winner')") + } + filters[#filters+1] = filter + + + end + + -- closed + + if phase == "closed" then + + local filter = { class = "subfilter", name = "closed" } + + filter[#filter+1] = { + name = "finished", + label = _"finished", + selector_modifier = function ( selector ) + selector:add_where ( "issue.state::text like 'finished_%'" ) + end + } + + filter[#filter+1] = { + name = "canceled", + label = _"canceled", + selector_modifier = function ( selector ) + selector:add_where ( "issue.closed NOTNULL AND NOT issue.state::text like 'finished_%' AND issue.accepted NOTNULL" ) end - end - } -end + } + + filter[#filter+1] = { + name = "not_accepted", + label = _"not admitted", + selector_modifier = function ( selector ) + selector:add_where ( "issue.closed NOTNULL AND issue.accepted ISNULL" ) + end + } -filters[#filters+1] = filter - + if member then + filter[#filter+1] = { + name = "voted", + label = _"voted by me", + selector_modifier = function(selector) + selector:left_join("direct_voter", "filter_direct_voter", { "filter_direct_voter.issue_id = issue.id AND filter_direct_voter.member_id = ?", member.id }) + selector:left_join("delegating_voter", "filter_delegating_voter", { "filter_delegating_voter.issue_id = issue.id AND filter_delegating_voter.member_id = ?", member.id }) + selector:add_where("filter_direct_voter.issue_id NOTNULL or filter_delegating_voter.issue_id NOTNULL") + end + } -if member then - local filter = { - name = "filter_interest", - } - if not for_member then - if not for_unit and not for_area then + filter[#filter+1] = { + name = "voted_direct", + label = _"voted directly by me", + selector_modifier = function(selector) + selector:join("direct_voter", "filter_direct_voter", { "filter_direct_voter.issue_id = issue.id AND filter_direct_voter.member_id = ?", member.id }) + end + } + filter[#filter+1] = { - name = "any", - label = _"All units", - selector_modifier = function() end + name = "voted_via_delegation", + label = _"voted via delegation", + selector_modifier = function(selector) + selector:join("delegating_voter", "filter_delegating_voter", { "filter_delegating_voter.issue_id = issue.id AND filter_delegating_voter.member_id = ?", member.id }) + end } + filter[#filter+1] = { - name = "unit", - label = _"My units", + name = "not_voted", + label = _"not voted by me", selector_modifier = function(selector) - selector:join("area", nil, "area.id = issue.area_id") - selector:join("privilege", nil, { "privilege.unit_id = area.unit_id AND privilege.member_id = ? AND privilege.voting_right", member.id }) + selector:left_join("direct_voter", "filter_direct_voter", { "filter_direct_voter.issue_id = issue.id AND filter_direct_voter.member_id = ?", member.id }) + selector:left_join("delegating_voter", "filter_delegating_voter", { "filter_delegating_voter.issue_id = issue.id AND filter_delegating_voter.member_id = ?", member.id }) + selector:add_where("filter_direct_voter.issue_id ISNULL AND filter_delegating_voter.issue_id ISNULL") end } end - if for_unit and not for_area then - filter[#filter+1] = { - name = "any", - label = _"All areas", - selector_modifier = function() end - } - end - if not for_area then - filter[#filter+1] = { - name = "area", - label = _"My areas", - selector_modifier = function(selector) - selector:join("membership", nil, { "membership.area_id = issue.area_id AND membership.member_id = ?", member.id }) - end - } - end - if for_area then - filter[#filter+1] = { - name = "any", - label = _"All issues", - selector_modifier = function() end - } - end - end - filter[#filter+1] = { - name = "issue", - label = _"Interested", - selector_modifier = function() end - } - filter[#filter+1] = { - name = "initiated", - label = _"Initiated", - selector_modifier = function(selector) - selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN initiator ON initiator.initiative_id = initiative.id AND initiator.member_id = ? AND initiator.accepted WHERE initiative.issue_id = issue.id)", member.id }) - end - } - filter[#filter+1] = { - name = "supported", - label = _"Supported", - selector_modifier = function() end - } - filter[#filter+1] = { - name = "potentially_supported", - label = _"Potentially supported", - selector_modifier = function() end - } - if state == 'closed' or (for_events) then - filter[#filter+1] = { - name = "voted", - label = _"Voted", - selector_modifier = function() end - } + + filters[#filters+1] = filter + + end - filters[#filters+1] = filter + end - -if app.session.member then - - local filter_interest = param.get_all_cgi()["filter_interest"] - - if filter_interest ~= "any" and filter_interest ~= nil and ( - filter_interest == "issue" or filter_interest == "supported" or filter_interest == "potentially_supported" or - (filter_interest == 'voted' and state ~= 'open') - ) then - - local function add_default_joins(selector) - selector:left_join("interest", "filter_interest", { "filter_interest.issue_id = issue.id AND filter_interest.member_id = ? ", member.id }) - selector:left_join("direct_interest_snapshot", "filter_interest_s", { "filter_interest_s.issue_id = issue.id AND filter_interest_s.member_id = ? AND filter_interest_s.event = issue.latest_snapshot_event", member.id }) - selector:left_join("delegating_interest_snapshot", "filter_d_interest_s", { "filter_d_interest_s.issue_id = issue.id AND filter_d_interest_s.member_id = ? AND filter_d_interest_s.event = issue.latest_snapshot_event", member.id }) - end - - filters[#filters+1] = { - name = "filter_delegation", - { - name = "any", - label = _"Direct and by delegation", - selector_modifier = function(selector) - add_default_joins(selector) - selector:add_where("CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN filter_interest.member_id NOTNULL ELSE filter_interest_s.member_id NOTNULL END OR filter_d_interest_s.member_id NOTNULL") - if filter_interest == "supported" then - selector:add_where({ - "CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN " .. - "EXISTS(SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN critical_opinion ON critical_opinion.initiative_id = initiative.id AND critical_opinion.member_id = supporter.member_id WHERE initiative.issue_id = issue.id AND critical_opinion.member_id ISNULL) " .. - "ELSE " .. - "EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = ? AND direct_supporter_snapshot.satisfied) " .. - "END OR EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = filter_d_interest_s.delegate_member_ids[array_upper(filter_d_interest_s.delegate_member_ids,1)] AND direct_supporter_snapshot.satisfied)", member.id, member.id, member.id }) - - elseif filter_interest == "potentially_supported" then - selector:add_where({ - "CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN " .. - "EXISTS(SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN critical_opinion ON critical_opinion.initiative_id = initiative.id AND critical_opinion.member_id = supporter.member_id WHERE initiative.issue_id = issue.id AND critical_opinion.member_id NOTNULL) " .. - "ELSE " .. - "EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = ? AND NOT direct_supporter_snapshot.satisfied) " .. - "END OR EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = filter_d_interest_s.delegate_member_ids[array_upper(filter_d_interest_s.delegate_member_ids,1)] AND NOT direct_supporter_snapshot.satisfied)", member.id, member.id, member.id }) - - elseif filter_interest == "voted" then - selector:add_where({ "EXISTS(SELECT 1 FROM direct_voter WHERE direct_voter.issue_id = issue.id AND direct_voter.member_id = ?) OR (issue.closed NOTNULL AND EXISTS(SELECT 1 FROM delegating_voter WHERE delegating_voter.issue_id = issue.id AND delegating_voter.member_id = ?)) ", member.id, member.id }) - - end - - end - }, - { - name = "direct", - label = _"Direct", - selector_modifier = function(selector) - add_default_joins(selector) - selector:add_where("CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN filter_interest.member_id NOTNULL ELSE filter_interest_s.member_id NOTNULL END") - - if filter_interest == "supported" then - selector:add_where({ - "CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN " .. - "EXISTS(SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN critical_opinion ON critical_opinion.initiative_id = initiative.id AND critical_opinion.member_id = supporter.member_id WHERE initiative.issue_id = issue.id AND critical_opinion.member_id ISNULL) " .. - "ELSE " .. - "EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = ? AND direct_supporter_snapshot.satisfied) " .. - "END", member.id, member.id }) - - elseif filter_interest == "potentially_supported" then - selector:add_where({ - "CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN " .. - "EXISTS(SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN critical_opinion ON critical_opinion.initiative_id = initiative.id AND critical_opinion.member_id = supporter.member_id WHERE initiative.issue_id = issue.id AND critical_opinion.member_id NOTNULL) " .. - "ELSE " .. - "EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = ? AND NOT direct_supporter_snapshot.satisfied) " .. - "END", member.id, member.id }) - elseif filter_interest == "voted" then - selector:add_where({ "EXISTS(SELECT 1 FROM direct_voter WHERE direct_voter.issue_id = issue.id AND direct_voter.member_id = ?) ", member.id }) - - end - end - }, - { - name = "delegated", - label = _"By delegation", - selector_modifier = function(selector) - add_default_joins(selector) - selector:add_where("filter_d_interest_s.member_id NOTNULL AND filter_interest.member_id ISNULL") - - if filter_interest == "supported" then - selector:add_where({ - "EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = filter_d_interest_s.delegate_member_ids[array_upper(filter_d_interest_s.delegate_member_ids,1)] AND direct_supporter_snapshot.satisfied)", member.id }) - - elseif filter_interest == "potentially_supported" then - selector:add_where({ - "EXISTS(SELECT 1 FROM direct_supporter_snapshot WHERE direct_supporter_snapshot.event = issue.latest_snapshot_event AND direct_supporter_snapshot.issue_id = issue.id AND direct_supporter_snapshot.member_id = filter_d_interest_s.delegate_member_ids[array_upper(filter_d_interest_s.delegate_member_ids,1)] AND NOT direct_supporter_snapshot.satisfied)", member.id }) - elseif filter_interest == "voted" then - selector:add_where({ "issue.closed NOTNULL AND EXISTS(SELECT 1 FROM delegating_voter WHERE delegating_voter.issue_id = issue.id AND delegating_voter.member_id = ?) ", member.id }) - - end - end - } - } - end - -end - -if state == 'open' and app.session.member and member.id == app.session.member_id and (param.get_all_cgi()["filter"] == "frozen") then - filters[#filters+1] = { - name = "filter_voting", - { - name = "any", - label = _"Any", - selector_modifier = function() end - }, - { - name = "not_voted", - label = _"Not voted", - selector_modifier = function(selector) - selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", member.id }) - selector:add_where("direct_voter.member_id ISNULL") - selector:left_join("non_voter", nil, { "non_voter.issue_id = issue.id AND non_voter.member_id = ?", member.id }) - selector:add_where("non_voter.member_id ISNULL") - end - }, - { - name = "voted", - label = _"Voted", - selector_modifier = function(selector) - selector:join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", member.id }) - end - }, - } -end - - - - -function filters:get_filter(group, name) - for i,grp in ipairs(self) do - if grp.name == group then - for i,entry in ipairs(grp) do - if entry.name == name then - return entry - end - end - end - end -end - -return filters \ No newline at end of file +return filters diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_head.lua --- a/app/main/issue/_head.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/issue/_head.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,3 +1,74 @@ local issue = param.get("issue", "table") +local initiative = param.get("initiative", "table") + +local member = param.get ( "member", "table" ) + + +ui.title ( function () + + ui.tag { + attr = { class = "unit" }, + content = function() + ui.link { + content = function() + ui.tag{ attr = { class = "name" }, content = issue.area.unit.name } + end, + module = "unit", view = "show", + id = issue.area.unit.id + } + end + } + ui.tag { attr = { class = "spacer" }, content = function() + slot.put ( " » " ) + end } + + ui.tag { + attr = { class = "area" }, + content = function() + ui.link { + content = function() + ui.tag{ attr = { class = "name" }, content = issue.area.name } + end, + module = "area", view = "show", + id = issue.area.id + } + end + } -execute.view{ module = "area", view = "_head", params = { area = issue.area } } + ui.tag { attr = { class = "spacer" }, content = function() + slot.put ( " » " ) + end } + + ui.tag { + attr = { class = "issue" }, + content = function() + -- issue link + ui.link { + text = _("#{policy_name} ##{issue_id}", { + policy_name = issue.policy.name, + issue_id = issue.id + } ), + module = "issue", view = "show", + id = issue.id + } + + slot.put ( " " ) + + if member then + execute.view { + module = "delegation", view = "_info", params = { + issue = issue, member = member, for_title = true + } + } + end + end + } + + if initiative then + ui.tag{ + attr = { class = "initiative" }, + content = initiative.display_name + } + end + +end ) -- ui.title diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_head2.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/issue/_head2.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,96 @@ +local issue = param.get("issue", "table") +local for_history = param.get("for_history", atom.boolean) + +ui.sectionHead( "issueInfo", function () + ui.container { attr = { class = "left" }, content = function() + ui.heading { level = 1, content = issue.name } + end } + if app.session.member then + ui.container { attr = { class = "right" }, content = function () + if issue.fully_frozen then + if issue.member_info.direct_voted then + ui.image { attr = { class = "icon48 right" }, static = "icons/48/voted_ok.png" } + ui.tag { content = _"You have voted" } + slot.put(" ") + if not issue.closed then + slot.put("
") + ui.link { + module = "vote", view = "list", + params = { issue_id = issue.id }, + text = _"change vote" + } + else + ui.link { + module = "vote", view = "list", + params = { issue_id = issue.id }, + text = _"show vote" + } + end + slot.put(" ") + elseif active_trustee_id then + ui.tag { content = _"You have voted via delegation" } + ui.link { + content = _"Show voting ballot", + module = "vote", view = "list", params = { + issue_id = issue.id, member_id = active_trustee_id + } + } + elseif not issue.closed then + ui.link { + attr = { class = "btn btn-default" }, + module = "vote", view = "list", + params = { issue_id = issue.id }, + text = _"vote now" + } + end + elseif not issue.closed then + if issue.member_info.own_participation then + ui.image { attr = { class = "icon48 right" }, static = "icons/48/eye.png" } + ui.tag{ content = _"You are interested in this issue" } + slot.put("
") + ui.link { + module = "interest", action = "update", + params = { issue_id = issue.id, delete = true }, + routing = { default = { + mode = "redirect", module = "issue", view = "show", id = issue.id + } }, + text = _"remove my interest" + } + else + ui.link { + attr = { class = "btn btn-default" }, + module = "interest", action = "update", + params = { issue_id = issue.id }, + routing = { default = { + mode = "redirect", module = "issue", view = "show", id = issue.id + } }, + text = _"add my interest" + } + end + end + end } + end +end) + +ui.container { + attr = { class = "ui_filter", style="clear: left; margin-top: 4px;" }, + content = function () + ui.container { + attr = { class = "ui_filter_head" }, + content = function () + + ui.link{ + attr = { class = not for_history and "active" or nil }, + text = _"Initiatives", + module = "issue", view = "show", id = issue.id + } + slot.put(" ") + ui.link{ + attr = { class = for_history and "active" or nil }, + text = _"History", + module = "issue", view = "history", id = issue.id + } + end + } + end +} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_list.lua --- a/app/main/issue/_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -local issues_selector = param.get("issues_selector", "table") -local member = param.get("for_member", "table") or app.session.member -local for_member = param.get("for_member", "table") -local for_state = param.get("for_state") -local for_unit = param.get("for_unit", atom.boolean) -local for_area = param.get("for_area", atom.boolean) - - -if for_state == "open" then - issues_selector:add_where("issue.closed ISNULL") -elseif for_state == "closed" then - issues_selector:add_where("issue.closed NOTNULL") -end - -ui.add_partial_param_names{ - "filter", - "filter_open", - "filter_voting", - "filter_interest", - "issue_list" -} - -local filters = execute.load_chunk{module="issue", chunk="_filters.lua", params = { - member = member, for_member = for_member, state = for_state, for_unit = for_unit, for_area = for_area -}} - -filters.content = function() - ui.paginate{ - per_page = tonumber(param.get("per_page") or 25), - selector = issues_selector, - content = function() - local highlight_string = param.get("highlight_string", "string") - local issues = issues_selector:exec() - issues:load_everything_for_member_id(member and member.id or nil) - - ui.container{ attr = { class = "issues" }, content = function() - - for i, issue in ipairs(issues) do - - execute.view{ module = "issue", view = "_show", params = { - issue = issue, for_listing = true, for_member = for_member - } } - - end - end } - end - } -end - -filters.opened = true -filters.selector = issues_selector - -if param.get("no_filter", atom.boolean) then - filters.content() -else - ui.filters(filters) -end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_list2.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/issue/_list2.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,373 @@ +local for_member = param.get ( "for_member", "table" ) +local for_unit = param.get ( "for_unit", "table" ) +local for_area = param.get ( "for_area", "table" ) +local for_issue = param.get ( "for_issue", "table" ) +local for_initiative = param.get ( "for_initiative", "table" ) +local for_sidebar = param.get("for_sidebar", atom.boolean) +local no_filter = param.get ( "no_filter", atom.boolean ) +local search = param.get ( "search" ) + +local limit = 25 + +local mode = param.get_all_cgi()["mode"] or "issue" + +if for_initiative or for_issue or for_member then + mode = "timeline" +end + +local selector + +if search then + + selector = Issue:get_search_selector(search) + + +elseif mode == "timeline" then + + local event_max_id = param.get_all_cgi()["event_max_id"] + + selector = Event:new_selector() + :add_order_by("event.id DESC") + :join("issue", nil, "issue.id = event.issue_id") + :add_field("now() - event.occurrence", "time_ago") + :limit(limit + 1) + + if event_max_id then + selector:add_where{ "event.id < ?", event_max_id } + end + + if for_member then + selector:add_where{ "event.member_id = ?", for_member.id } + end + + if for_initiative then + selector:add_where{ "event.initiative_id = ?", for_initiative.id } + end + + +elseif mode == "issue" then + + selector = Issue:new_selector() + +end + +if for_unit then + selector:join("area", nil, "area.id = issue.area_id") + selector:add_where{ "area.unit_id = ?", for_unit.id } +elseif for_area then + selector:add_where{ "issue.area_id = ?", for_area.id } +elseif for_issue then + selector:add_where{ "issue.id = ?", for_issue.id } +end + +if not search and app.session.member_id then + selector + :left_join("interest", "_interest", { + "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id + } ) + :add_field("(_interest.member_id NOTNULL)", "is_interested") + :left_join("delegating_interest_snapshot", "_delegating_interest", { [[ + _delegating_interest.issue_id = issue.id AND + _delegating_interest.member_id = ? AND + _delegating_interest.event = issue.latest_snapshot_event + ]], app.session.member.id } ) + :add_field("_delegating_interest.delegate_member_ids[1]", "is_interested_by_delegation_to_member_id") + :add_field("_delegating_interest.delegate_member_ids[array_upper(_delegating_interest.delegate_member_ids, 1)]", "is_interested_via_member_id") + :add_field("array_length(_delegating_interest.delegate_member_ids, 1)", "delegation_chain_length") +end + +function doit() + + local last_event_id + + local items = selector:exec() + + if #items < 1 then + ui.section( function() + ui.sectionRow( function() + ui.heading{ level = 2, content = _"No results for this selection" } + end ) + end ) + return + end + + local row_class = "sectionRow" + if for_sidebar then + row_class = "sidebarRow" + end + + if mode == "timeline" then + local issues = items:load ( "issue" ) + local initiative = items:load ( "initiative" ) + items:load ( "suggestion" ) + items:load ( "member" ) + issues:load_everything_for_member_id ( app.session.member_id ) + initiative:load_everything_for_member_id ( app.session.member_id ) + elseif mode == "issue" then + items:load_everything_for_member_id ( app.session.member_id ) + end + + local class = "section" + if mode == "timeline" then + class = class .. " events" + elseif mode == "issue" then + class = class .. " issues" + end + + ui.container{ attr = { class = class }, content = function() + + local last_event_date + for i, item in ipairs(items) do + local event + local issue + if mode == "timeline" then + event = item + issue = item.issue + elseif mode == "issue" then + event = {} + issue = item + end + + last_event_id = event.id + + local class = "event " .. row_class + if event.suggestion_id then + class = class .. " suggestion" + end + + ui.container{ attr = { class = class }, content = function() + local event_name + local negative_event = false + + local days_ago_text + + if mode == "timeline" then + event_name = event.event_name + + if event.event == "issue_state_changed" then + if event.state == "discussion" then + event_name = _"Discussion started" + elseif event.state == "verification" then + event_name = _"Verification started" + elseif event.state == "voting" then + event_name = _"Voting started" + elseif event.state == "finished_with_winner" then + event_name = event.state_name + elseif event.state == "finished_without_winner" then + event_name = event.state_name + negative_event = true + else + event_name = event.state_name + negative_event = true + end + elseif event.event == "initiative_revoked" then + negative_event = true + end + + if event.time_ago == 0 then + days_ago_text = _("today at #{time}", { time = format.time(event.occurrence) }) + elseif event.time_ago == 1 then + days_ago_text = _("yesterday at #{time}", { time = format.time(event.occurrence) }) + else + days_ago_text = _("#{interval} ago", { interval = format.interval_text ( event.time_ago ) } ) + end + + elseif mode == "issue" then + event_name = issue.state_name + if issue.state_time_left:sub(1,1) ~= "-" then + days_ago_text = _( "#{interval} left", { + interval = format.interval_text ( issue.state_time_left ) + }) + elseif issue.closed then + days_ago_text = _( "#{interval} ago", { + interval = format.interval_text ( issue.closed_ago ) + }) + else + days_ago_text = _"phase ends soon" + end + if issue.closed and not issue.fully_frozen then + negative_event = true + end + if issue.state == "finished_without_winner" then + negative_event = true + end + if issue.state == "canceled_no_initiative_admitted" then + negative_event = true + end + if issue.state == "canceled_by_admin" then + negative_event = true + end + end + + local class= "event_info" + + if negative_event then + class = class .. " negative" + end + + if mode == "timeline" then + ui.container{ attr = { class = class }, content = function () + ui.tag { content = event_name } + slot.put ( " " ) + ui.tag{ attr = { class = "event_time" }, content = days_ago_text } + end } + end + + if not for_issue and not for_initiative then + ui.container{ attr = { class = "issue_context" }, content = function() + ui.link{ + module = "unit", view = "show", id = issue.area.unit_id, + attr = { class = "unit" }, text = issue.area.unit.name + } + slot.put ( " " ) + ui.link{ + module = "area", view = "show", id = issue.area_id, + attr = { class = "area" }, text = issue.area.name + } + slot.put ( " " ) + execute.view{ + module = "delegation", view = "_info", params = { + issue = issue, member = for_member + } + } + end } + ui.container{ attr = { class = "issue_info" }, content = function() + ui.link{ + attr = { class = "issue" }, + text = _("#{policy} ##{id}", { policy = issue.policy.name, id = issue.id }), + module = "issue", + view = "show", + id = issue.id + } + + end } + end + + if mode ~= "timeline" + or event.state == "finished_with_winner" + or event.state == "finished_without_winner" + then + local initiative = issue.initiatives[1] + if initiative then + util.initiative_pie(initiative) + end + end + + if mode == "issue" then + ui.container{ attr = { class = class }, content = function () + ui.tag { content = event_name } + slot.put ( " " ) + ui.tag{ attr = { class = "event_time" }, content = days_ago_text } + end } + elseif mode == "timeline" + and not for_issue + and event.event ~= "issue_state_changed" + then + slot.put("
") + end + + if event.suggestion_id then + ui.container{ attr = { class = "suggestion" }, content = function() + ui.link{ + text = format.string(event.suggestion.name, { + truncate_at = 160, truncate_suffix = true + }), + module = "initiative", view = "show", id = event.initiative.id, + params = { suggestion_id = event.suggestion_id }, + anchor = "s" .. event.suggestion_id + } + end } + end + + if not for_initiative and (not for_issue or event.initiative_id) then + + ui.container{ attr = { class = "initiative_list" }, content = function() + if event.initiative_id then + local initiative = event.initiative + + execute.view{ module = "initiative", view = "_list", params = { + issue = issue, + initiative = initiative, + for_event = mode == "timeline" and not (event.state == issue.state) + + } } + else + local initiatives = issue.initiatives + execute.view{ module = "initiative", view = "_list", params = { + issue = issue, + initiatives = initiatives, + for_event = mode == "timeline" and not (event.state == issue.state) + } } + end + end } + end + + end } + end + + if mode == "timeline" then + if for_sidebar then + ui.container { attr = { class = row_class }, content = function () + ui.link{ + attr = { class = "moreLink" }, + text = _"Show full history", + module = "initiative", view = "history", id = for_initiative.id + } + end } + elseif #items > limit then + ui.container { attr = { class = row_class }, content = function () + ui.link{ + attr = { class = "moreLink" }, + text = _"Show older events", + module = request.get_module(), + view = request.get_view(), + id = for_unit and for_unit.id or for_area and for_area.id or for_issue and for_issue.id or for_member and for_member.id, + params = { + mode = "timeline", + event_max_id = last_event_id, + tab = param.get_all_cgi()["tab"], + phase = param.get_all_cgi()["phase"], + closed = param.get_all_cgi()["closed"] + } + } + end } + elseif #items < 1 then + ui.container { attr = { class = row_class }, content = _"No more events available" } + end + end + + end } + +end + + +local filters = {} + +if not for_initiative and not for_issue and not no_filter then + filters = execute.load_chunk{module="issue", chunk="_filters.lua", params = { + for_events = mode == "timeline" and true or false, + member = app.session.member, + for_member = for_member, + state = for_state, + for_unit = for_unit and true or false, + for_area = for_area and true or false + }} +end + +filters.opened = true +filters.selector = selector + +if mode == "timeline" then + filters.content = doit +else + filters.content = function() + ui.paginate{ + selector = selector, + per_page = 25, + content = doit + } + end +end + +ui.filters(filters) + \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_show.lua --- a/app/main/issue/_show.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,310 +0,0 @@ -local issue = param.get("issue", "table") -local initiative_limit = param.get("initiative_limit", atom.integer) -local for_member = param.get("for_member", "table") -local for_listing = param.get("for_listing", atom.boolean) -local for_initiative = param.get("for_initiative", "table") -local for_initiative_id = for_initiative and for_initiative.id or nil - -local direct_voter -if app.session.member_id then - direct_voter = issue.member_info.direct_voted -end - -local voteable = app.session.member_id and issue.state == 'voting' and - app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) - -local vote_comment_able = app.session.member_id and issue.closed and direct_voter - -local vote_link_text -if voteable then - vote_link_text = direct_voter and _"Change vote" or _"Vote now" -elseif vote_comment_able then - vote_link_text = direct_voter and _"Update voting comment" -end - - -local class = "issue" -if issue.is_interested then - class = class .. " interested" -elseif issue.is_interested_by_delegation_to_member_id then - class = class .. " interested_by_delegation" -end - -ui.container{ attr = { class = class }, content = function() - - execute.view{ module = "delegation", view = "_info", params = { issue = issue, member = for_member } } - - if for_listing then - ui.container{ attr = { class = "content" }, content = function() - ui.link{ - module = "unit", view = "show", id = issue.area.unit_id, - attr = { class = "unit_link" }, text = issue.area.unit.name - } - slot.put(" ") - ui.link{ - module = "area", view = "show", id = issue.area_id, - attr = { class = "area_link" }, text = issue.area.name - } - end } - end - - ui.container{ attr = { class = "title" }, content = function() - - ui.link{ - attr = { class = "issue_id" }, - text = _("#{policy_name} ##{issue_id}", { - policy_name = issue.policy.name, - issue_id = issue.id - }), - module = "issue", - view = "show", - id = issue.id - } - end } - - ui.tag{ - attr = { class = "content issue_policy_info" }, - tag = "div", - content = function() - - ui.tag{ attr = { class = "event_name" }, content = issue.state_name } - - if issue.closed then - slot.put(" · ") - ui.tag{ content = format.interval_text(issue.closed_ago, { mode = "ago" }) } - elseif issue.state_time_left then - slot.put(" · ") - if issue.state_time_left:sub(1,1) == "-" then - if issue.state == "admission" then - ui.tag{ content = _("Discussion starts soon") } - elseif issue.state == "discussion" then - ui.tag{ content = _("Verification starts soon") } - elseif issue.state == "verification" then - ui.tag{ content = _("Voting starts soon") } - elseif issue.state == "voting" then - ui.tag{ content = _("Counting starts soon") } - end - else - ui.tag{ content = format.interval_text(issue.state_time_left, { mode = "time_left" }) } - end - end - - end - } - - local links = {} - - if vote_link_text then - links[#links+1] ={ - content = vote_link_text, - module = "vote", - view = "list", - params = { issue_id = issue.id } - } - end - - if voteable and not direct_voter then - if not issue.member_info.non_voter then - links[#links+1] ={ - content = _"Do not vote directly", - module = "vote", - action = "non_voter", - params = { issue_id = issue.id }, - routing = { - default = { - mode = "redirect", - module = request.get_module(), - view = request.get_view(), - id = param.get_id_cgi(), - params = param.get_all_cgi() - } - } - } - else - links[#links+1] = { attr = { class = "action" }, content = _"Do not vote directly" } - links[#links+1] ={ - in_brackets = true, - content = _"Cancel [nullify]", - module = "vote", - action = "non_voter", - params = { issue_id = issue.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() - } - } - } - end - end - - if not for_member or for_member.id == app.session.member_id then - - if app.session.member_id then - - if issue.member_info.own_participation then - if issue.closed then - links[#links+1] = { content = _"You were interested" } - else - links[#links+1] = { content = _"You are interested" } - end - end - - if not issue.closed and not issue.fully_frozen then - if issue.member_info.own_participation then - links[#links+1] = { - in_brackets = true, - text = _"Withdraw", - module = "interest", - action = "update", - params = { issue_id = issue.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() - } - } - } - elseif app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) then - links[#links+1] = { - text = _"Add my interest", - module = "interest", - action = "update", - params = { issue_id = issue.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 - - if not issue.closed and app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) then - if issue.member_info.own_delegation_scope ~= "issue" then - links[#links+1] = { text = _"Delegate issue", module = "delegation", view = "show", params = { issue_id = issue.id, initiative_id = for_initiative_id } } - else - links[#links+1] = { text = _"Change issue delegation", module = "delegation", view = "show", params = { issue_id = issue.id, initiative_id = for_initiative_id } } - end - end - end - - if config.issue_discussion_url_func then - local url = config.issue_discussion_url_func(issue) - links[#links+1] = { - attr = { target = "_blank" }, - external = url, - content = _"Discussion on issue" - } - end - - if config.etherpad and app.session.member then - links[#links+1] = { - attr = { target = "_blank" }, - external = issue.etherpad_url, - content = _"Issue pad" - } - end - - - if app.session.member_id and app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) then - if not issue.fully_frozen and not issue.closed then - links[#links+1] = { - attr = { class = "action" }, - text = _"Create alternative initiative", - module = "initiative", - view = "new", - params = { issue_id = issue.id } - } - end - end - - end - - ui.container{ attr = { class = "content actions" }, content = function() - for i, link in ipairs(links) do - if link.in_brackets then - slot.put(" (") - elseif i > 1 then - slot.put(" · ") - end - if link.module or link.external then - ui.link(link) - else - ui.tag(link) - end - if link.in_brackets then - slot.put(")") - end - end - end } - - if not for_listing then - if issue.state == "canceled_by_admin" then - ui.container{ - attr = { class = "not_admitted_info" }, - content = function() - ui.container{ content = _("This issue has been canceled by administrative intervention.") } - slot.put("
") - if issue.admin_notice then - ui.container{ content = function() slot.put(encode.html_newlines(issue.admin_notice)) end } - end - end - } - elseif issue.admin_notice then - ui.container{ - attr = { class = "not_admitted_info" }, - content = function() slot.put(encode.html_newlines(issue.admin_notice)) end - } - end - - if issue.state == "canceled_issue_not_accepted" then - local policy = issue.policy - ui.container{ - attr = { class = "not_admitted_info" }, - content = _("This issue has been canceled. It failed the quorum of #{quorum}.", { quorum = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den) }) - } - elseif - issue.state:sub(1, #("canceled_")) == "canceled_" and - issue.state ~= "canceled_by_admin" - then - ui.container{ - attr = { class = "not_admitted_info" }, - content = _("This issue has been canceled.") - } - end - end - - ui.container{ attr = { class = "initiative_list content" }, content = function() - - local initiatives_selector = issue:get_reference_selector("initiatives") - local highlight_string = param.get("highlight_string") - if highlight_string then - initiatives_selector:add_field( {'"highlight"("initiative"."name", ?)', highlight_string }, "name_highlighted") - end - execute.view{ - module = "initiative", - view = "_list", - params = { - issue = issue, - initiatives_selector = initiatives_selector, - highlight_initiative = for_initiative, - highlight_string = highlight_string, - no_sort = true, - limit = (for_listing or for_initiative) and 5 or nil, - for_member = for_member - } - } - end } -end } - diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_sidebar_issue.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/issue/_sidebar_issue.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,39 @@ +local issue = param.get("issue", "table") +local hide_initiatives = param.get("hide_initiatives", atom.boolean) +local highlight_initiative_id = param.get ( "highlight_initiative_id", "number" ) + +ui.sidebar ( "tab-whatcanido", function () + + ui.sidebarHead( function() + ui.heading { + level = 2, + content = _"Competing initiatives" + } + end ) + + execute.view { + module = "initiative", view = "_list", + params = { + issue = issue, + initiatives = issue.initiatives, + highlight_initiative_id = highlight_initiative_id + } + } + if #issue.initiatives == 1 then + ui.sidebarSection( function () + + if not issue.closed and not (issue.state == "voting") then + ui.container { content = function() + ui.tag { content = _"Currently this is the only initiative in this issue, because nobody started a competing initiative (yet)." } + if app.session.member and app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) then + slot.put(" ") + ui.tag { content = _"To create a competing initiative see below." } + end + end } + else + ui.container { content = _"This is the only initiative in this issue, because nobody started a competing initiative." } + end + end ) + end + +end ) -- ui.sidebar diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_sidebar_members.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/issue/_sidebar_members.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,65 @@ +local issue = param.get("issue", "table") +local initiative = param.get("initiative", "table") + +if app.session:has_access("all_pseudonymous") then + ui.sidebar ( "tab-members", function () + + local text = _"Interested members" + if issue.state == "finished_with_winner" or issue.state == "finished_without_winner" then + text = _"Voters" + end + + ui.sidebarHead( function() + ui.heading{ + level = 2, content = text + } + end ) + + local interested_members_selector + + if issue.state == "finished_with_winner" or issue.state == "finished_without_winner" then + if initiative then + interested_members_selector = Member:new_selector() + :join("issue", nil, { "issue.id = ?", issue.id }) + :join("direct_voter", nil, { "direct_voter.issue_id = ? AND direct_voter.member_id = member.id", issue.id }) + :join("vote", nil, { "vote.member_id = member.id AND vote.initiative_id = ?", initiative.id }) + :add_field("direct_voter.weight", "voter_weight") + :add_field("vote.grade") + :add_field("direct_voter.comment", "voter_comment") + else + interested_members_selector = Member:new_selector() + :join("issue", nil, { "issue.id = ?", issue.id }) + :join("direct_voter", nil, { "direct_voter.issue_id = ? AND direct_voter.member_id = member.id", issue.id }) + :add_field("direct_voter.weight", "voter_weight") + :add_field("direct_voter.comment", "voter_comment") + end + else + interested_members_selector= issue:get_reference_selector("interested_members_snapshot") + :join("issue", nil, "issue.id = direct_interest_snapshot.issue_id") + :add_field("direct_interest_snapshot.weight") + :add_where("direct_interest_snapshot.event = issue.latest_snapshot_event") + :limit(25) + + if initiative then + interested_members_selector:left_join("direct_supporter_snapshot", nil, { "direct_supporter_snapshot.initiative_id = ? AND direct_interest_snapshot.issue_id = direct_supporter_snapshot.issue_id AND direct_supporter_snapshot.member_id = direct_interest_snapshot.member_id AND direct_supporter_snapshot.event = issue.latest_snapshot_event", initiative.id }) + interested_members_selector:add_field("direct_supporter_snapshot.member_id NOTNULL", "supporter") + interested_members_selector:add_field("satisfied", "supporter_satisfied") + end + end + + execute.view{ + module = "member", + view = "_list", + params = { + issue = issue, + initiative = initiative, + members_selector = interested_members_selector, + no_filter = true, no_paginate = true, + member_class = "sidebarRow sidebarRowNarrow", + for_votes = issue.state == "finished_with_winner" or issue.state == "finished_without_winner" + } + } + + end ) + +end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_sidebar_state.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/issue/_sidebar_state.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,171 @@ +local issue = param.get("issue", "table") +local initiative = param.get("initiative", "table") + +local view_module +local view_id + +if initiative then + issue = initiative.issue + view_module = "initiative" + view_id = initiative.id +else + view_module = "issue" + view_id = issue.id +end + +ui.sidebar( "tab-whatcanido", function() + + ui.sidebarHead( function() + ui.heading{ level = 2, content = function() + ui.link{ + content = issue.name, + module = "issue", view = "show", id = issue.id + } + end } + end ) + + local current_occured = false + local failed = false + + for i, state in ipairs{ "admission", "discussion", "verification", "voting" } do + local current = state == issue.state + + if current then + current_occured = true + end + + local phase_success = ( + (state == "admission" and issue.accepted) + or (state == "discussion" and issue.half_frozen) + or (state == "verification" and issue.fully_frozen and issue.state ~= "canceled_no_initiative_admitted") + or (state == "voting" and issue.closed and issue.state ~= "canceled_no_initiative_admitted" and issue.state ~= "canceled_by_admin") + ) + + if not failed then + ui.sidebarSection( "sidebarRowNarrow" .. (current and " highlightedx" or ""), function() + + local state_names = { + admission = _"Admission", + discussion = _"Discussion", + verification = _"Verification", + voting = _"Voting" + } + + local state_name = "(" .. i .. ") " .. state_names[state] or state + + local function quorum_text(policy, quorum) + local num + local den + + if quorum == 1 then + num = policy.issue_quorum_num + den = policy.issue_quorum_den + elseif quorum == 2 then + num = policy.initiative_quorum_num + den = policy.initiative_quorum_den + end + + if den == 100 then + return _("#{percentage}%", { percentage = num }) + else + return num .. "/" .. den + end + + end + + local quorum + if state == "admission" then + quorum = quorum_text(issue.policy, 1) + elseif state == "verification" then + quorum = quorum_text(issue.policy, 2) + end + + if current then + local time_left + if issue.state_time_left:sub(1,1) ~= "-" then + time_left = format.interval_text(issue.state_time_left, { mode = "time_left" }) + else + time_left = "phase ends soon" + end + + ui.tag{ attr = { class = "right" }, + content = time_left + } + elseif current_occured then + local phase_duration = issue[state .. "_time"] + ui.tag{ attr = { class = "right" }, + content = _("#{duration}", { + duration = format.interval_text(phase_duration) + } ) + } + else + local text = "failed" + if quorum then + text = _("failed #{quorum}", { quorum = quorum }) + end + if phase_success then + if quorum then + text = _("reached #{quorum}", { quorum = quorum }) + else + text = _"finished" + end + elseif issue.state == "canceled_revoked_before_accepted" or + issue.state == "canceled_after_revocation_during_discussion" or + issue.state == "canceled_after_revocation_during_verification" + then + text = _"revoked" + elseif issue.state == "canceled_by_admin" then + text = _"canceled" + end + + ui.tag{ attr = { class = "right" }, + content = text + } + end + + ui.heading{ level = 3, content = function() + if current then + ui.image{ attr = { class = "icon16" }, static = "icons/32/phase_current.png" } + elseif not current_occured and not phase_success then + ui.image{ attr = { class = "icon16" }, static = "icons/32/phase_failed.png" } + elseif current_occured then + ui.image{ attr = { class = "icon16" }, static = "icons/32/empty.png" } + else + ui.image{ attr = { class = "icon16" }, static = "icons/32/phase_finished.png" } + end + slot.put(" ") + ui.tag{ content = state_name } + end } + + local help_texts = { + admission = _"As soon as one initiative of this issue reaches #{quorum} support, the issue will go into discussion phase.", + discussion = _"During the discussion phase the issue is debated between initiators while the initiatives are improved by suggestions from the supporters.", + verification = _"During the verification phase the initiative drafts cannot be changed anymore.", + voting = _"On this issue can be voted now." + } + if current then + -- ui.container { content = help_texts[state] } + end + + + end ) + end + + if not phase_success and not current and not current_occured then + failed = true + end + end + + if issue.closed then + ui.sidebarSection( function() + ui.heading { level = 1, content = issue.state_name } + end ) + if issue.admin_notice then + ui.sidebarSection( function() + ui.heading { level = 3, content = _"Administrative notice:" } + slot.put(encode.html_newlines(issue.admin_notice)) + end ) + end + end + +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/_sidebar_whatcanido.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/issue/_sidebar_whatcanido.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,631 @@ +local issue = param.get("issue", "table") +local initiative = param.get("initiative", "table") +local member = param.get("member", "table") or app.session.member + +if initiative then + issue = initiative.issue +end + +local privileged_to_vote = app.session.member and app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) + +local active_trustee_id +if member then + if not issue.member_info.own_participation then + if issue.member_info.first_trustee_participation then + active_trustee_id = issue.member_info.first_trustee_id + elseif issue.member_info.other_trustee_participation then + active_trustee_id = issue.member_info.other_trustee_id + end + end +end + +ui.sidebar ( "tab-whatcanido", function () + + ui.sidebarHeadWhatCanIDo() + + local supporter + + if initiative and app.session.member_id then + supporter = app.session.member:get_reference_selector("supporters") + :add_where{ "initiative_id = ?", initiative.id } + :optional_object_mode() + :exec() + end + + local view_module + local view_id + + if initiative then + issue = issue + view_module = "initiative" + view_id = initiative.id + else + view_module = "issue" + view_id = issue.id + end + + local initiator + if initiative and app.session.member_id then + initiator = Initiator:by_pk(initiative.id, app.session.member.id) + end + + local initiators + + if initiative then + local initiators_members_selector = initiative:get_reference_selector("initiating_members") + :add_field("initiator.accepted", "accepted") + :add_order_by("member.name") + if initiator and initiator.accepted then + initiators_members_selector:add_where("initiator.accepted ISNULL OR initiator.accepted") + else + initiators_members_selector:add_where("initiator.accepted") + end + + initiators = initiators_members_selector:exec() + end + + if initiator and + initiator.accepted and + not issue.fully_frozen and + not issue.closed and + not initiative.revoked + then + + ui.container { attr = { class = "sidebarRow" }, content = function () + ui.heading { level = 3, content = function() + ui.tag { content = _"You are initiator of this initiative" } + end } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + module = "draft", view = "new", + params = { initiative_id = initiative.id }, + content = _"edit proposal and/or reasons" + } + end } + ui.tag { tag = "li", content = function () + ui.link{ + attr = { class = "action" }, + module = "initiative", view = "add_initiator", + params = { initiative_id = initiative.id }, + content = _"invite another initiator" + } + end } + if #initiative.initiators > 1 then + ui.tag { tag = "li", content = function () + ui.link{ + module = "initiative", view = "remove_initiator", + params = { initiative_id = initiative.id }, + content = _"remove an initiator" + } + end } + end + ui.tag { tag = "li", content = function () + ui.link{ + module = "initiative", view = "revoke", id = initiative.id, + content = _"revoke initiative" + } + end } + end } + end } + end + + -- invited as initiator + if initiator and initiator.accepted == nil and not initiative.issue.half_frozen and not initiative.issue.closed then + ui.container { attr = { class = "sidebarRow highlighted" }, content = function () + ui.heading { level = 3, content = function() + ui.tag { content = _"You are invited to become initiator of this initiative" } + end } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag{ tag = "li", content = function () + ui.link{ + content = _"accept invitation", + module = "initiative", + action = "accept_invitation", + id = initiative.id, + routing = { + default = { + mode = "redirect", + module = request.get_module(), + view = request.get_view(), + id = param.get_id_cgi(), + params = param.get_all_cgi() + } + } + } + end } + + ui.tag{ tag = "li", content = function () + ui.link{ + content = _"refuse invitation", + module = "initiative", + action = "reject_initiator_invitation", + params = { + initiative_id = initiative.id, + member_id = app.session.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 } + end + + + if privileged_to_vote and issue.member_info.first_trustee_id then + local member = Member:by_id(issue.member_info.first_trustee_id) + ui.sidebarSection( function () + ui.container { attr = { class = "right" }, content = function() + execute.view{ + module = "member_image", + view = "_show", + params = { + member = member, + image_type = "avatar", + show_dummy = true + } + } + end } + if issue.member_info.own_delegation_scope == "unit" then + ui.heading{ level = 3, content = _"You delegated this organizational unit" } + elseif issue.member_info.own_delegation_scope == "area" then + ui.heading{ level = 3, content = _"You delegated this subject area" } + elseif issue.member_info.own_delegation_scope == "issue" then + ui.heading{ level = 3, content = _"You delegated this issue" } + end + + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + if issue.member_info.own_delegation_scope == "area" or + issue.member_info.own_delegation_scope == "unit" then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + issue_id = issue.id, + initiative_id = initiative and initiative.id or nil + }, + content = _"change/revoke delegation only for this issue" + } + end } + end + if issue.member_info.own_delegation_scope == "unit" then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + unit_id = issue.area.unit_id, + }, + content = _("change/revoke delegation of organizational unit", { + unit_name = issue.area.unit.name + }) + } + end } + elseif issue.member_info.own_delegation_scope == "area" then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + area_id = issue.area_id, + }, + content = _"change/revoke delegation of subject area" + } + end } + end + if issue.member_info.own_delegation_scope == nil then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + issue_id = issue.id, + initiative_id = initiative and initiative.id or nil + }, + content = _"choose issue delegatee" + } + end } + elseif issue.member_info.own_delegation_scope == "issue" then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + issue_id = issue.id, + initiative_id = initiative and initiative.id or nil + }, + content = _"change/revoke issue delegation" + } + end } + end + end } + + if issue.member_info.first_trustee_id and issue.member_info.own_participation then + local text = _"As long as you are interested in this issue yourself, the delegation is suspended for this issue, but it will be applied again in the voting phase unless you vote yourself." + if issue.state == "voting" then + text = _"This delegation is suspended, because you voted yourself." + end + ui.container { content = text } + end + end ) + end + + if privileged_to_vote and not issue.closed and not issue.fully_frozen then + if issue.member_info.own_participation then + ui.sidebarSection( function () + ui.container{ attr = { class = "right" }, content = function() + ui.image{ attr = { class = "right" }, static = "icons/48/eye.png" } + if issue.member_info.weight and issue.member_info.weight > 1 then + slot.put("
") + ui.tag{ + attr = { class = "right" }, + content = "+" .. issue.member_info.weight - 1 + } + end + end } + ui.heading{ level = 3, content = _("You are interested in this issue", { id = issue.id }) } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + if issue.member_info.weight and issue.member_info.weight > 1 then + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show_incoming", + params = { issue_id = issue.id, member_id = app.session.member_id }, + content = _("you have #{count} incoming delegations", { + count = issue.member_info.weight - 1 + }) + } + end } + end + ui.tag { tag = "li", content = function () + ui.link { + module = "interest", action = "update", + routing = { default = { + mode = "redirect", module = view_module, view = "show", id = view_id + } }, + params = { issue_id = issue.id, delete = true }, + text = _"remove my interest" + } + end } + end } + end ) + else + ui.sidebarSection( function () + ui.heading{ level = 3, content = _("I want to participate in this issue", { id = issue.id }) } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link { + module = "interest", action = "update", + params = { issue_id = issue.id }, + routing = { default = { + mode = "redirect", module = view_module, view = "show", id = view_id + } }, + text = _"add my interest" + } + end } + ui.tag { tag = "li", content = _"browse through the competing initiatives" } + end } + end ) + end + + if initiative then + + if not initiative.member_info.supported or active_trustee_id then + ui.container { attr = { class = "sidebarRow" }, content = function () + ui.heading { level = 3, content = function() + ui.tag { content = _"I like this initiative and I want to support it" } + end } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link { + module = "initiative", action = "add_support", + routing = { default = { + mode = "redirect", module = "initiative", view = "show", id = initiative.id + } }, + id = initiative.id, + text = _"add my support" + } + end } + end } + end } + + else -- if not supported + ui.container { attr = { class = "sidebarRow" }, content = function () + if initiative.member_info.satisfied then + ui.image{ attr = { class = "right icon48" }, static = "icons/32/support_satisfied.png" } + else + ui.image{ attr = { class = "right icon48" }, static = "icons/32/support_unsatisfied.png" } + end + ui.heading { level = 3, content = _"You are supporting this initiative" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + if not initiative.member_info.satisfied then + ui.tag { tag = "li", content = function () + ui.tag { content = function () + ui.link { + external = "#suggestions", + content = _"you restricted your support by rating suggestions as must or must not" + } + end } + end } + end + ui.tag { tag = "li", content = function () + ui.tag { content = function () + ui.link { + xattr = { class = "btn btn-remove" }, + module = "initiative", action = "remove_support", + routing = { default = { + mode = "redirect", module = "initiative", view = "show", id = initiative.id + } }, + id = initiative.id, + text = _"remove my support" + } + end } + end } + end } + end } + + end -- not supported + + ui.container { attr = { class = "sidebarRow" }, content = function () + ui.heading { level = 3, content = _"I want to improve this initiative" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + if issue.state == "verification" then + ui.tag { tag = "li", content = _"this issue is in verification phase, therefore the initiative text cannot be updated anymore" } + elseif issue.state == "voting" then + ui.tag { tag = "li", content = _"this issue is in voting phase, therefore the initiative text cannot be updated anymore" } + else + + if initiative.member_info.initiated then + ui.tag { tag = "li", content =_"take a look at the suggestions of your supporters" } + ui.tag { tag = "li", content =_"if you like to implement a suggestion in your proposal and/or reasons, update your initiative draft" } + ui.tag { tag = "li", content =_"to argue about suggestions, just add your arguments to your reasons in the initiative draft, so your supporters can learn about your opinion" } + end + + if not initiative.member_info.supported or active_trustee_id then + ui.tag { tag = "li", content =_"add your support (see above) and rate or write new suggestions (and thereby restrict your support to certain conditions if necessary)" } + else + ui.tag { tag = "li", content = _"take a look at the suggestions (see left) and rate them" } + ui.tag { tag = "li", content = function () + ui.link { + module = "suggestion", view = "new", params = { + initiative_id = initiative.id + }, + content = _"write a new suggestion" + } + end } + end + end + end } + end } + + end + + if + (issue.state == "admission" or + issue.state == "discussion" or + issue.state == "verification") + then + ui.sidebarSection( function () + if initiative then + ui.heading{ level = 3, content = _"I don't like this initiative and I want to add my opinion or counter proposal" } + else + ui.heading{ level = 3, content = _"I don't like any of the initiative in this issue and I want to add my opinion or counter proposal" } + end + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link { + module = "issue", view = "show", id = issue.id, + content = _"take a look at the competing initiatives" + } + end } + ui.tag { tag = "li", content = function () + ui.link { + module = "initiative", view = "new", + params = { issue_id = issue.id }, + content = _"start a new competing initiative" + } + end } + end } + end ) + end + + if not issue.member_info.first_trustee_id then + ui.sidebarSection( function () + ui.heading{ level = 3, content = _"I want to delegate this issue" } + + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + issue_id = issue.id, + initiative_id = initiative and initiative.id or nil + }, + content = _"choose issue delegatee" + } + end } + end } + end ) + end + + end + + if initiator and initiator.accepted == false then + ui.container { attr = { class = "sidebarRow" }, content = function () + ui.heading { level = 3, content = function() + ui.tag { content = _"You refused to become initiator of this initiative" } + end } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag{ tag = "li", content = function () + ui.link{ + text = _"allow invitation again", + module = "initiative", + action = "remove_initiator", + params = { + initiative_id = initiative.id, + member_id = app.session.member.id + }, + routing = { + ok = { + mode = "redirect", + module = "initiative", + view = "show", + id = initiative.id + } + } + } + end } + end } + end } + end + + + + if privileged_to_vote then + + if initiative and + (issue.state == "admission" or + issue.state == "discussion" or + issue.state == "verification") + then + + elseif issue.state == "verification" then + + elseif issue.state == "voting" then + if not issue.member_info.direct_voted then + if not issue.member_info.non_voter then + ui.container { attr = { class = "sidebarRow" }, content = function () + ui.heading { level = 3, content = _"I like to vote on this issue:" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = function () + if not issue.closed then + ui.link { + xattr = { class = "btn btn-vote" }, + module = "vote", view = "list", + params = { issue_id = issue.id }, + text = _"vote now" + } + end + end } + end } + end } + end } + end + ui.container { attr = { class = "sidebarRow" }, content = function () + if not issue.member_info.non_voter then + ui.heading { level = 3, content = _"I don't like to vote this issue (myself):" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + content = _"do not notify me about this voting anymore", + module = "vote", + action = "non_voter", + params = { issue_id = issue.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 } + else + ui.heading { level = 3, content = _"You do not like to vote this issue (yourself)" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + in_brackets = true, + content = _"discard", + module = "vote", + action = "non_voter", + params = { issue_id = issue.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() + } + } + } + end } + end } + end + end } + else + ui.container { attr = { class = "sidebarRow" }, content = function () + ui.heading { level = 3, content = _"I like to change/revoke my vote:" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.tag { content = function () + if not issue.closed then + ui.link { + xattr = { class = "btn btn-vote" }, + module = "vote", view = "list", + params = { issue_id = issue.id }, + text = _"change my vote" + } + end + end } + end } + ui.tag { tag = "li", content = function () + ui.tag { content = function () + if not issue.closed then + ui.link { + module = "vote", action = "update", + params = { + issue_id = issue.id, + discard = true + }, + routing = { + default = { + mode = "redirect", + module = "issue", + view = "show", + id = issue.id + } + }, + text = _"discard my vote" + } + end + end } + end } + end } + + end } + + end + end + end + + if app.session.member and not privileged_to_vote then + ui.sidebarSection( _"You are not entitled to vote in this unit" ) + end + + if issue.closed then + ui.container { attr = { class = "sidebarRow" }, content = function () + ui.heading { level = 3, content = _"This issue is closed" } + end } + end + + if initiative and config.tell_others and config.tell_others.initiative then + ui.container { attr = { class = "sidebarRow" }, content = function () + + ui.heading { level = 3, content = _"Tell others about this initiative:" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + + for i, link in ipairs (config.tell_others.initiative(initiative)) do + ui.tag { tag = "li", content = function () + ui.link ( link ) + end } + end + + end } + end } + end + + +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/history.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/issue/history.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,47 @@ +local issue = Issue:by_id(param.get_id()) +issue:load_everything_for_member_id ( app.session.member_id ) + +execute.view { + module = "issue", view = "_head", + params = { issue = issue, member = app.session.member } +} + +execute.view { + module = "issue", view = "_sidebar_issue", params = { + issue = issue, + hide_initiatives = true + } +} + +execute.view{ module = "issue", view = "_sidebar_state", params = { + issue = issue +} } + +execute.view { + module = "issue", view = "_sidebar_whatcanido", params = { + issue = issue + } +} + +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = issue + } +} + + + +ui.section( function() + + execute.view{ + module = "issue", view = "_head2", params = { + issue = issue, for_history = true + } + } + + execute.view { + module = "issue", view = "_list2", params = { for_issue = issue } + } + +end ) + diff -r a6c7bf07badb -r 701a5cf6b067 app/main/issue/list.lua --- a/app/main/issue/list.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -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 a6c7bf07badb -r 701a5cf6b067 app/main/issue/show.lua --- a/app/main/issue/show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/issue/show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,52 +1,126 @@ -local issue = Issue:by_id(param.get_id()) +local issue = Issue:by_id ( param.get_id () ) + +if not issue then + execute.view { module = "index", view = "404" } + request.set_status("404 Not Found") + return +end + +local initiatives = issue.initiatives + if app.session.member_id then - issue:load_everything_for_member_id(app.session.member_id) + issue:load_everything_for_member_id ( app.session.member_id ) + initiatives:load_everything_for_member_id ( app.session.member_id ) end if not app.html_title.title then - app.html_title.title = _("Issue ##{id}", { id = issue.id }) + app.html_title.title = _("Issue ##{id}", { id = issue.id }) end -slot.select("head", function() - execute.view{ module = "area", view = "_head", params = { area = issue.area } } -end) - -util.help("issue.show") +execute.view { + module = "issue", view = "_head", + params = { issue = issue, member = app.session.member } +} -slot.select("head", function() - execute.view{ module = "issue", view = "_show", params = { issue = issue } } -end ) - -if app.session:has_access("all_pseudonymous") then +execute.view{ module = "issue", view = "_sidebar_state", params = { + issue = issue +} } - ui.container{ attr = { class = "heading" }, content = _"Interested members" } - - local interested_members_selector = issue:get_reference_selector("interested_members_snapshot") - :join("issue", nil, "issue.id = direct_interest_snapshot.issue_id") - :add_field("direct_interest_snapshot.weight") - :add_where("direct_interest_snapshot.event = issue.latest_snapshot_event") +execute.view { + module = "issue", view = "_sidebar_whatcanido", params = { + issue = issue + } +} - execute.view{ - module = "member", - view = "_list", - params = { - issue = issue, - members_selector = interested_members_selector +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = issue + } +} + +ui.section( function () + + execute.view{ + module = "issue", view = "_head2", params = { + issue = issue } } - ui.container{ attr = { class = "heading" }, content = _"Details" } - - execute.view{ - module = "issue", - view = "_details", - params = { issue = issue } - } + if issue.initiatives[1].rank == 1 then + execute.view{ module = "initiative", view = "_sidebar_state", params = { + initiative = issue.initiatives[1] + } } + end -end + ui.sectionRow( function () + execute.view { + module = "initiative", view = "_list", + params = { + issue = issue, + initiatives = initiatives + } + } + end ) + +end ) -if issue.snapshot then - slot.put("
") - ui.field.timestamp{ label = _"Last snapshot:", value = issue.snapshot } -end +ui.section(function() + ui.sectionHead( function() + ui.heading { level = 1, content = _"Details" } + end ) + local policy = issue.policy + ui.form{ + record = issue, + readonly = true, + attr = { class = "sectionRow form" }, + content = function() + if issue.snapshot then + ui.field.timestamp{ label = _"Last counting:", value = issue.snapshot } + end + ui.field.text{ label = _"Population", name = "population" } + ui.field.timestamp{ label = _"Created at", name = "created" } + if policy.polling then + ui.field.text{ label = _"Admission time", value = _"Implicitly admitted" } + else + ui.field.text{ label = _"Admission time", value = format.interval_text(issue.admission_time_text) } + ui.field.text{ + label = _"Issue quorum", + value = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den) + } + if issue.population then + ui.field.text{ + label = _"Currently required", + value = math.ceil(issue.population * policy.issue_quorum_num / policy.issue_quorum_den) + } + end + end + if issue.accepted then + ui.field.timestamp{ label = _"Accepted at", name = "accepted" } + end + ui.field.text{ label = _"Discussion time", value = format.interval_text(issue.discussion_time_text) } + if issue.half_frozen then + ui.field.timestamp{ label = _"Half frozen at", name = "half_frozen" } + end + ui.field.text{ label = _"Verification time", value = format.interval_text(issue.verification_time_text) } + ui.field.text{ + label = _"Initiative quorum", + value = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den) + } + if issue.population then + ui.field.text{ + label = _"Currently required", + value = math.ceil(issue.population * (issue.policy.initiative_quorum_num / issue.policy.initiative_quorum_den)), + } + end + if issue.fully_frozen then + ui.field.timestamp{ label = _"Fully frozen at", name = "fully_frozen" } + end + ui.field.text{ label = _"Voting time", value = format.interval_text(issue.voting_time_text) } + if issue.closed then + ui.field.timestamp{ label = _"Closed", name = "closed" } + end + end + } +end ) + diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_action/update.lua --- a/app/main/member/_action/update.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/_action/update.lua Thu Jul 10 01:19:48 2014 +0200 @@ -23,11 +23,11 @@ end if not config.locked_profile_fields.statement then - local formatting_engine = param.get("formatting_engine") + local formatting_engine = param.get("formatting_engine") or config.enforce_formatting_engine local formatting_engine_valid = false - for fe, dummy in pairs(config.formatting_engine_executeables) do - if formatting_engine == fe then + for i, fe in pairs(config.formatting_engines) do + if formatting_engine == fe.id then formatting_engine_valid = true end end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_event_list.lua --- a/app/main/member/_event_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -local member = param.get("member", "table") -local events = param.get_all_cgi()["events"] or "personal" - -ui.container{ attr = { class = "ui_filter" }, content = function() - ui.container{ attr = { class = "ui_filter_head" }, content = function() - - ui.link{ - attr = { class = events == "personal" and "ui_tabs_link active" or nil }, - text = _"My areas and issues", - module = "index", view = "index", params = { tab = "timeline", events = "personal" } - } - - slot.put(" ") - - ui.link{ - attr = { class = events == "global" and "active" or nil }, - text = _"Everything", - module = "index", view = "index", params = { tab = "timeline", events = "global" } - } - end } -end } - -if events == "personal" then - execute.view{ - module = "event", view = "_list" - } -elseif events == "global" then - execute.view{ - module = "event", view = "_list", params = { global = true } - } -end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_list.lua --- a/app/main/member/_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -6,16 +6,20 @@ local trustee = param.get("trustee", "table") local initiator = param.get("initiator", "table") local for_votes = param.get("for_votes", atom.boolean) +local no_filter = param.get ( "no_filter", atom.boolean ) +local no_paginate = param.get ( "no_paginate", atom.boolean ) local paginator_name = param.get("paginator_name") +local member_class = param.get("member_class") + if initiative or issue then if for_votes then members_selector:left_join("delegating_voter", "_member_list__delegating_voter", { "_member_list__delegating_voter.issue_id = issue.id AND _member_list__delegating_voter.member_id = ?", app.session.member_id }) - members_selector:add_field("_member_list__delegating_voter.delegate_member_ids", "delegate_member_ids") + members_selector:add_field("member.id = ANY(_member_list__delegating_voter.delegate_member_ids)", "in_delegation_chain") else members_selector:left_join("delegating_interest_snapshot", "_member_list__delegating_interest", { "_member_list__delegating_interest.event = issue.latest_snapshot_event AND _member_list__delegating_interest.issue_id = issue.id AND _member_list__delegating_interest.member_id = ?", app.session.member_id }) - members_selector:add_field("_member_list__delegating_interest.delegate_member_ids", "delegate_member_ids") + members_selector:add_field("member.id = ANY(_member_list__delegating_interest.delegate_member_ids)", "in_delegation_chain") end end @@ -23,9 +27,11 @@ local filter = { name = "member_list" } -if issue or initiative then -end - +filter[#filter+1] = { + name = "last_activity", + label = _"Latest activity", + selector_modifier = function(selector) selector:add_order_by("last_login DESC NULLS LAST, id DESC") end +} filter[#filter+1] = { name = "newest", label = _"Newest", @@ -48,9 +54,8 @@ selector_modifier = function(selector) selector:add_order_by("name DESC") end } -local ui_filters = ui.filters if issue or initiative then - ui_filters = function(args) args.content() end + no_filter = true if for_votes then members_selector:add_order_by("voter_weight DESC, name, id") else @@ -58,27 +63,30 @@ end end -ui_filters{ - label = _"Change order", - selector = members_selector, - filter, - content = function() - ui.paginate{ - name = paginator_name, - anchor = paginator_name, - selector = members_selector, - per_page = 50, - content = function() - ui.container{ - attr = { class = "member_list" }, - content = function() - local members = members_selector:exec() - for i, member in ipairs(members) do +function list_members() + local ui_paginate = ui.paginate + if no_paginate then + ui_paginate = function (args) args.content() end + end + ui_paginate{ + name = paginator_name, + anchor = paginator_name, + selector = members_selector, + per_page = 50, + content = function() + ui.container{ + attr = { class = "member_list" }, + content = function() + local members = members_selector:exec() + + for i, member in ipairs(members) do + ui.sectionRow( function() execute.view{ module = "member", view = "_show_thumb", params = { + class = member_class, member = member, initiative = initiative, issue = issue, @@ -86,13 +94,24 @@ initiator = initiator } } - end + end ) + end - end - } - slot.put('
') - end - } - end -} + end + } + end + } +end + + +if no_filter then + list_members() +else + ui.filters { + label = _"Change order", + selector = members_selector, + content = list_members, + filter + } +end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_profile.lua --- a/app/main/member/_profile.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/_profile.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,6 +1,6 @@ local member = param.get("member", "table") -local include_private_data = param.get("include_private_data", atom.boolean) +local for_registration = param.get("for_registration", atom.boolean) if not member then local member_id = param.get("member_id", atom.integer) @@ -10,34 +10,23 @@ end ui.form{ - attr = { class = "member_statement member vertical" }, + attr = { class = "form" }, record = member, readonly = true, content = function() - slot.put("
") - - ui.container{ - attr = { class = "right" }, - content = function() - - execute.view{ - module = "member_image", - view = "_show", - params = { - member = member, - image_type = "photo" + if not for_registration then + ui.container { attr = { class = "member_photo" }, content = function() + execute.view{ + module = "member_image", + view = "_show", + params = { + member = member, + image_type = "photo" + } } - } - - ui.container{ - attr = { class = "contact_data" }, - content = function() - end - } - - end - } + end } + end if member.identification then ui.field.text{ label = _"Identification", name = "identification" } @@ -45,8 +34,11 @@ if member.name then ui.field.text{ label = _"Screen name", name = "name" } end - if include_private_data and member.login then + if for_registration and member.login then ui.field.text{ label = _"Login name", name = "login" } + end + + if for_registration and member.notify_email then ui.field.text{ label = _"Notification email", name = "notify_email" } end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_show.lua --- a/app/main/member/_show.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -local member = param.get("member", "table") - -local tabs = { - module = "member", - view = "show_tab", - static_params = { - member_id = member.id - } -} - -tabs[#tabs+1] = { - name = "profile", - label = _"Profile", - icon = { static = "icons/16/application_form.png" }, - module = "member", - view = "_profile", - params = { member = member }, -} - -local areas_selector = member:get_reference_selector("areas") -tabs[#tabs+1] = { - name = "areas", - label = _"Units and areas", - icon = { static = "icons/16/package.png" }, - module = "index", - view = "_member_home", - params = { areas_selector = areas_selector, member = member, for_member = true }, -} - -tabs[#tabs+1] = { - name = "timeline", - label = _"Latest events", - module = "event", - view = "_list", - params = { for_member = member } -} - -tabs[#tabs+1] = { - name = "open", - label = _"Open issues", - module = "issue", - view = "_list", - link_params = { - filter_interest = "issue", - }, - params = { - for_state = "open", - for_member = member, - issues_selector = Issue:new_selector() - :add_where("issue.closed ISNULL") - :add_order_by("coalesce(issue.fully_frozen + issue.voting_time, issue.half_frozen + issue.verification_time, issue.accepted + issue.discussion_time, issue.created + issue.admission_time) - now()") - } -} - -tabs[#tabs+1] = { - name = "closed", - label = _"Closed issues", - module = "issue", - view = "_list", - link_params = { - filter_interest = "issue", - }, - params = { - for_state = "closed", - for_member = member, - issues_selector = Issue:new_selector() - :add_where("issue.closed NOTNULL") - :add_order_by("issue.closed DESC") - - } -} - - -local outgoing_delegations_selector = member:get_reference_selector("outgoing_delegations") - :left_join("issue", "_member_showtab_issue", "_member_showtab_issue.id = delegation.issue_id") - :add_where("_member_showtab_issue.closed ISNULL") -tabs[#tabs+1] = { - name = "outgoing_delegations", - label = _"Outgoing delegations" .. " (" .. tostring(outgoing_delegations_selector:count()) .. ")", - icon = { static = "icons/16/table_go.png" }, - module = "delegation", - view = "_list", - params = { delegations_selector = outgoing_delegations_selector, outgoing = true }, -} - -local incoming_delegations_selector = member:get_reference_selector("incoming_delegations") - :left_join("issue", "_member_showtab_issue", "_member_showtab_issue.id = delegation.issue_id") - :add_where("_member_showtab_issue.closed ISNULL") -tabs[#tabs+1] = { - name = "incoming_delegations", - label = _"Incoming delegations" .. " (" .. tostring(incoming_delegations_selector:count()) .. ")", - icon = { static = "icons/16/table_go.png" }, - module = "delegation", - view = "_list", - params = { delegations_selector = incoming_delegations_selector, incoming = true }, -} - -local contacts_selector = member:get_reference_selector("saved_members"):add_where("public") -tabs[#tabs+1] = { - name = "contacts", - label = _"Contacts" .. " (" .. tostring(contacts_selector:count()) .. ")", - icon = { static = "icons/16/book_edit.png" }, - module = "member", - view = "_list", - params = { members_selector = contacts_selector }, -} - -ui.tabs(tabs) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_show_thumb.lua --- a/app/main/member/_show_thumb.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/_show_thumb.lua Thu Jul 10 01:19:48 2014 +0200 @@ -5,6 +5,8 @@ local initiative = param.get("initiative", "table") local trustee = param.get("trustee", "table") +local class = param.get("class") + local name_html if member.name_highlighted then name_html = encode.highlight(member.name_highlighted) @@ -21,15 +23,19 @@ container_class = container_class .. " not_informed" end -local in_delegation_chain = false -if member.delegate_member_ids then +if class then + container_class = container_class .. " " .. class +end + +local in_delegation_chain = member.in_delegation_chain +--[[if member.delegate_member_ids then for member_id in member.delegate_member_ids:gmatch("(%w+)") do if tonumber(member_id) == member.id then in_delegation_chain = true end end end - +--]] if in_delegation_chain or ((issue or initiative) and member.id == app.session.member_id) then container_class = container_class .. " in_delegation_chain" end @@ -37,140 +43,165 @@ ui.container{ attr = { class = container_class }, content = function() - ui.container{ - attr = { class = "flags" }, - content = function() + + local function doit() + execute.view{ + module = "member_image", + view = "_show", + params = { + member = member, + image_type = "avatar", + show_dummy = true + } + } + ui.tag{ + attr = { class = "member_name" }, + content = function() slot.put(name_html) end + } + end + + if app.session:has_access("everything") then + ui.link{ + attr = { title = _"Show member" }, + module = "member", + view = "show", + id = member.id, + content = doit + } + else + ui.tag{ content = doit } + end - if not member.active then - local text = _"inactive" - ui.tag{ content = text } + if member.grade then + slot.put ( " " ) + ui.link{ + module = "vote", + view = "list", + params = { + issue_id = initiative.issue.id, + member_id = member.id, + }, + content = function() + if member.grade > 0 then + ui.image{ + attr = { + alt = _"Voted yes", + title = _"Voted yes", + class = "icon24 right" + }, + static = "icons/32/support_satisfied.png" + } + elseif member.grade < 0 then + ui.image{ + attr = { + alt = _"Voted no", + title = _"Voted no", + class = "icon24 right" + }, + static = "icons/32/voted_no.png" + } + else + ui.image{ + attr = { + alt = _"Abstention", + title = _"Abstention", + class = "icon24 right" + }, + static = "icons/16/bullet_yellow.png" + } + end + end + } + end + + if (member.voter_comment) then + ui.link{ + module = "vote", + view = "list", + params = { + issue_id = issue.id, + member_id = member.id, + }, + content = function() ui.image{ - attr = { alt = text, title = text }, - static = "icons/16/cross.png" - } - end - - if member.grade then - ui.link{ - module = "vote", - view = "list", - params = { - issue_id = initiative.issue.id, - member_id = member.id, + attr = { + alt = _"Voting comment available", + title = _"Voting comment available", + class = "icon24 right" }, - content = function() - if (member.voter_comment) then - ui.image{ - attr = { - alt = _"Voting comment available", - title = _"Voting comment available" - }, - static = "icons/16/comment.png" - } - end - - if member.grade > 0 then - ui.image{ - attr = { - alt = _"Voted yes", - title = _"Voted yes" - }, - static = "icons/16/thumb_up_green.png" - } - elseif member.grade < 0 then - ui.image{ - attr = { - alt = _"Voted no", - title = _"Voted no" - }, - static = "icons/16/thumb_down_red.png" - } - else - ui.image{ - attr = { - alt = _"Abstention", - title = _"Abstention" - }, - static = "icons/16/bullet_yellow.png" - } - end - end + static = "icons/16/comment.png" } end + } + end - local weight = 0 - if member.weight then - weight = member.weight - end - if member.voter_weight then - weight = member.voter_weight - end - if (issue or initiative) and weight > 1 then - local module - if issue then - module = "interest" - elseif initiative then - if member.voter_weight then - module = "vote" - else - module = "supporter" - end - end - ui.link{ - attr = { - class = in_delegation_chain and "in_delegation_chain" or nil, - title = _"Number of incoming delegations, follow link to see more details" - }, - content = _("+ #{weight}", { weight = weight - 1 }), - module = module, - view = "show_incoming", - params = { - member_id = member.id, - initiative_id = initiative and initiative.id or nil, - issue_id = issue and issue.id or nil - } - } - end + local weight = 0 + if member.weight then + weight = member.weight + end + if member.voter_weight then + weight = member.voter_weight + end + + if (issue or initiative) and weight > 1 then + local module = "interest" + if member.voter_weight then + module = "vote" + end - if initiator and initiator.accepted then - if member.accepted == nil then - slot.put(_"Invited") - elseif member.accepted == false then - slot.put(_"Rejected") - end - end - - if member.is_informed == false then - local text = _"Member has not approved latest draft" - ui.image{ - attr = { alt = text, title = text }, - static = "icons/16/help_yellow.png" - } - end - + slot.put ( " " ) + ui.link{ + attr = { + class = in_delegation_chain and "in_delegation_chain" or nil, + title = _"Number of incoming delegations, follow link to see more details" + }, + content = _("+ #{weight}", { weight = weight - 1 }), + module = module, + view = "show_incoming", + params = { + member_id = member.id, + initiative_id = initiative and initiative.id or nil, + issue_id = issue and issue.id or nil + } + } + end + + if member.supporter then + slot.put ( " " ) + if member.supporter_satisfied then + local text = _"supporter" + ui.image{ attr = { class = "icon24 right", alt = text, title = text }, static = "icons/32/support_satisfied.png" } + else + local text = _"supporter with restricting suggestions" + ui.image{ attr = { class = "icon24 right", alt = text, title = text }, static = "icons/32/support_unsatisfied.png" } end - } + end - ui.link{ - attr = { title = _"Show member" }, - module = "member", - view = "show", - id = member.id, - content = function() - execute.view{ - module = "member_image", - view = "_show", - params = { - member = member, - image_type = "avatar", - show_dummy = true - } - } - ui.container{ - attr = { class = "member_name" }, - content = function() slot.put(name_html) end - } + if not member.active then + slot.put ( " " ) + local text = _"member inactive" + ui.image{ + attr = { alt = text, title = text }, + static = "icons/16/cross.png" + } + ui.tag{ content = _"inactive" } + end + + if initiator and initiator.accepted then + if member.accepted == nil then + slot.put(_"Invited") + elseif member.accepted == false then + slot.put(_"Rejected") end - } + end + + if member.is_informed == false then + local text = _"Member has not approved latest draft" + ui.image{ + attr = { alt = text, title = text }, + static = "icons/16/help_yellow.png" + } + end + end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_sidebar_contacts.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/member/_sidebar_contacts.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,86 @@ +local member = param.get("member", "table") + +local public_contacts_selector = Contact:build_selector{ + public = true, + member_id = member.id, + order = "name" +} + +local private_contacts_selector = Contact:build_selector{ + public = false, + member_id = member.id, + order = "name" +} + +ui.sidebar( "tab-members", function() + + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Published contacts" } + end ) + + --ui.sidebarSection( function() + + if public_contacts_selector:count() == 0 then + ui.sidebarSection( function() + ui.field.text{ value = _"No published contacts" } + end ) + else + ui.paginate{ + selector = public_contacts_selector, + name = "contacts", + content = function() + local contacts = public_contacts_selector:exec() + for i, contact in ipairs(contacts) do + ui.sidebarSection( "sidebarRowNarrow", function() + execute.view{ module = "member_image", view = "_show", params = { + member_id = contact.other_member.id, class = "micro_avatar", + popup_text = contact.other_member.name, + image_type = "avatar", show_dummy = true, + } } + slot.put(" ") + ui.link{ + content = contact.other_member.name, + module = "member", + view = "show", + id = contact.other_member.id + } + end ) + end + end + } + end + --end ) + + + if member.id == app.session.member.id and private_contacts_selector:count() > 0 then + + ui.sidebarHead( function() + ui.heading { level = 2, content = _"Private contacts" } + end ) + + ui.paginate{ + selector = private_contacts_selector, + name = "contacts", + content = function() + local contacts = private_contacts_selector:exec() + for i, contact in ipairs(contacts) do + ui.sidebarSection( "sidebarRowNarrow", function() + execute.view{ module = "member_image", view = "_show", params = { + member_id = contact.other_member.id, class = "micro_avatar", + popup_text = contact.other_member.name, + image_type = "avatar", show_dummy = true, + } } + slot.put(" ") + ui.link{ + content = contact.other_member.name, + module = "member", + view = "show", + id = contact.other_member.id + } + end ) + end + end + } + + end +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/_sidebar_whatcanido.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/member/_sidebar_whatcanido.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,326 @@ +local member = param.get("member", "table") + +ui.sidebar( "tab-whatcanido", function() + + if not member.active then + ui.container{ attr = { class = "sidebarSection" }, content = function() + slot.put(" · ") + ui.tag{ + attr = { class = "interest deactivated_member_info" }, + content = _"This member is inactive" + } + end } + end + + if member.locked then + ui.container{ attr = { class = "sidebarSection" }, content = function() + slot.put(" · ") + ui.tag{ + attr = { class = "interest deactivated_member_info" }, + content = _"This member is locked" + } + end } + end + + + ui.sidebarHeadWhatCanIDo() + + if member.id == app.session.member_id and not app.session.needs_delegation_check then + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to customize my profile" } + ui.tag{ tag = "ul", attr = { class = "ul" }, content = function() + ui.tag{ tag = "li", content = function() + ui.link{ + content = _"edit profile data", + module = "member", + view = "edit" + } + end } + ui.tag{ tag = "li", content = function() + ui.link{ + content = _"change avatar/photo", + module = "member", + view = "edit_images" + } + end } + end } + end ) + --[[ + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to manage my saved contacts" } + ui.tag{ tag = "ul", attr = { class = "ul" }, content = function() + ui.tag{ tag = "li", content = function() + + ui.link{ + content = _"show saved contacts", + module = 'contact', + view = 'list' + } + + end } + end } + end ) + --]] + + ui.sidebarSection( function() + + ui.heading { level = 3, content = _"I want to change account settings" } + + local pages = {} + + pages[#pages+1] = { view = "settings_notification", text = _"notification settings" } + if not config.locked_profile_fields.notify_email then + pages[#pages+1] = { view = "settings_email", text = _"change your notification email address" } + end + if not config.locked_profile_fields.name then + pages[#pages+1] = { view = "settings_name", text = _"change your screen name" } + end + if not config.locked_profile_fields.login then + pages[#pages+1] = { view = "settings_login", text = _"change your login" } + end + pages[#pages+1] = { view = "settings_password", text = _"change your password" } + pages[#pages+1] = { view = "developer_settings", text = _"developer settings" } + + if config.download_dir then + pages[#pages+1] = { module = "index", view = "download", text = _"database download" } + end + + ui.tag{ tag = "ul", attr = { class = "ul" }, content = function() + for i, page in ipairs(pages) do + ui.tag{ tag = "li", content = function() + ui.link{ + module = page.module or "member", + view = page.view, + text = page.text + } + end } + end + end } + end ) + + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to logout" } + ui.tag{ tag = "ul", attr = { class = "ul" }, content = function() + ui.tag{ tag = "li", content = function() + ui.link{ + text = _"logout", + module = 'index', + action = 'logout', + routing = { + default = { + mode = "redirect", + module = "index", + view = "index" + } + } + } + end } + end } + end ) + + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to change the interface language" } + ui.tag{ tag = "ul", attr = { class = "ul" }, content = function() + for i, lang in ipairs(config.enabled_languages) do + + local langcode + + locale.do_with({ lang = lang }, function() + langcode = _("[Name of Language]") + end) + + ui.tag{ tag = "li", content = function() + ui.link{ + content = _('Select language "#{langcode}"', { langcode = langcode }), + 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 } + end ) + elseif app.session.member_id and not (member.id == app.session.member.id) then + + ui.sidebarSection( function () + + local contact = Contact:by_pk(app.session.member.id, member.id) + if not contact then + ui.heading { level = 3, content = _"I want to save this member as contact (i.e. to use as delegatee)" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + text = _"add to my list of public contacts", + module = "contact", + action = "add_member", + id = 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 } + ui.tag { tag = "li", content = function () + ui.link{ + text = _"add to my list of private contacts", + module = "contact", + action = "add_member", + id = 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 } + elseif contact.public then + ui.heading { level = 3, content = _"You saved this member as contact (i.e. to use as delegatee) and others can see it" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + text = _"make this contact private", + module = "contact", + action = "add_member", + id = contact.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() + } + } + } + end } + ui.tag { tag = "li", content = function () + ui.link{ + text = _"remove from my contact list", + module = "contact", + action = "remove_member", + id = contact.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 } + else + ui.heading { level = 3, content = _"You saved this member as contact (i.e. to use as delegatee)" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + text = _"make this contact public", + module = "contact", + action = "add_member", + id = contact.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 } + ui.tag { tag = "li", content = function () + ui.link{ + text = _"remove from my contact list", + module = "contact", + action = "remove_member", + id = contact.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 + end ) + + ui.sidebarSection( function() + local ignored_member = IgnoredMember:by_pk(app.session.member.id, member.id) + if not ignored_member then + ui.heading { level = 3, content = _"I do not like to hear from this member" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + attr = { class = "interest" }, + text = _"block this member", + module = "member", + action = "update_ignore_member", + id = 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 } + else + ui.heading { level = 3, content = _"You blocked this member (i.e. you will not be notified about this members actions)" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link{ + text = _"unblock member", + module = "member", + action = "update_ignore_member", + id = member.id, + params = { delete = 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 } + end + end ) + end +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/developer_settings.lua --- a/app/main/member/developer_settings.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/developer_settings.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,96 +1,116 @@ ui.title(_"Developer settings") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} local setting_key = "liquidfeedback_frontend_developer_features" local setting = Setting:by_pk(app.session.member.id, setting_key) -if setting then - ui.form{ - attr = { class = "vertical" }, - module = "member", - action = "update_stylesheet_url", - routing = { - ok = { - mode = "redirect", - module = "index", - view = "index" +if true or setting then + ui.section( function() + ui.sectionHead( function () + ui.heading{ content = "CSS development settings" } + end ) + + ui.sectionRow( function() + ui.form{ + attr = { class = "vertical" }, + module = "member", + action = "update_stylesheet_url", + routing = { + ok = { + mode = "redirect", + module = "member", + view = "show", + id = app.session.member_id + } + }, + content = function() + local setting_key = "liquidfeedback_frontend_stylesheet_url" + local setting = Setting:by_pk(app.session.member.id, setting_key) + local value = setting and setting.value + ui.field.text{ + label = "stylesheet URL", + name = "stylesheet_url", + value = value + } + ui.submit{ value = _"Set URL" } + end } - }, - content = function() - local setting_key = "liquidfeedback_frontend_stylesheet_url" - local setting = Setting:by_pk(app.session.member.id, setting_key) - local value = setting and setting.value - ui.field.text{ - label = _"Stylesheet URL", - name = "stylesheet_url", - value = value - } - ui.submit{ value = _"Set URL" } - end - } + end ) + end ) end -ui.heading{ content = _"API keys" } +ui.section( function() + ui.sectionHead( function () + ui.heading{ content = "API keys" } + end ) -local member_applications = MemberApplication:new_selector() - :add_where{ "member_id = ?", app.session.member.id } - :add_order_by("name, id") - :exec() - -if #member_applications > 0 then + ui.sectionRow( function() + local member_applications = MemberApplication:new_selector() + :add_where{ "member_id = ?", app.session.member.id } + :add_order_by("name, id") + :exec() + + if #member_applications > 0 then - ui.list{ - records = member_applications, - columns = { - { - name = "name", - label = _"Name" - }, - { - name = "access_level", - label = _"Access level" - }, - { - name = "key", - label = _"API Key" - }, - { - name = "last_usage", - label = "Last usage" - }, - { - content = function(member_application) - ui.link{ - text = _"Delete", - module = "member", action = "update_api_key", id = member_application.id, - params = { delete = true }, - routing = { - default = { - mode = "redirect", - module = "member", - view = "developer_settings" + ui.list{ + records = member_applications, + columns = { + { + name = "name", + label = "Name" + }, + { + name = "access_level", + label = "Access level" + }, + { + name = "key", + label = "API Key" + }, + { + name = "last_usage", + label = "Last usage" + }, + { + content = function(member_application) + ui.link{ + text = "delete", + module = "member", action = "update_api_key", id = member_application.id, + params = { delete = true }, + routing = { + default = { + mode = "redirect", + module = "member", + view = "developer_settings" + } + } } - } - } - end - }, - } - } + end + }, + } + } -else - - slot.put(_"Currently no API key is set.") - slot.put(" ") - ui.link{ - text = _"Generate API key", - module = "member", - action = "update_api_key", - routing = { - default = { - mode = "redirect", + else + + slot.put(_"Currently no API key is set.") + slot.put(" ") + ui.link{ + text = _"Generate API key", module = "member", - view = "developer_settings" + action = "update_api_key", + routing = { + default = { + mode = "redirect", + module = "member", + view = "developer_settings" + } + } } - } - } -end + end + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/edit.lua --- a/app/main/member/edit.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/edit.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,6 +1,10 @@ -ui.title(_"Edit my profile") +ui.titleMember(_"Edit your profile data") -util.help("member.edit", _"Edit my page") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} ui.form{ record = app.session.member, @@ -16,73 +20,98 @@ } }, content = function() - ui.field.text{ label = _"Identification", name = "identification", readonly = true } - ui.field.text{ label = _"Organizational unit", name = "organizational_unit", readonly = config.locked_profile_fields.organizational_unit } - ui.field.text{ label = _"Internal posts", name = "internal_posts", readonly = config.locked_profile_fields.internal_posts } - ui.field.text{ label = _"Real name", name = "realname", readonly = config.locked_profile_fields.realname } - ui.field.text{ label = _"Birthday" .. " YYYY-MM-DD ", name = "birthday", attr = { id = "profile_birthday" }, readonly = config.locked_profile_fields.birthday } - ui.script{ static = "gregor.js/gregor.js" } - util.gregor("profile_birthday", "document.getElementById('timeline_search_date').form.submit();") - ui.field.text{ label = _"Address", name = "address", multiline = true, readonly = config.locked_profile_fields.address } - ui.field.text{ label = _"email", name = "email", readonly = config.locked_profile_fields.email } - ui.field.text{ label = _"xmpp", name = "xmpp_address", readonly = config.locked_profile_fields.xmpp_address } - ui.field.text{ label = _"Website", name = "website", readonly = config.locked_profile_fields.website } - ui.field.text{ label = _"Phone", name = "phone", readonly = config.locked_profile_fields.phone } - ui.field.text{ label = _"Mobile phone", name = "mobile_phone", readonly = config.locked_profile_fields.mobile_phone } - ui.field.text{ label = _"Profession", name = "profession", readonly = config.locked_profile_fields.profession } - ui.field.text{ label = _"External memberships", name = "external_memberships", multiline = true, readonly = config.locked_profile_fields.external_memberships } - ui.field.text{ label = _"External posts", name = "external_posts", multiline = true, readonly = config.locked_profile_fields.external_posts } + + ui.section( function() + + ui.sectionHead( function() + ui.heading{ level = 1, content = _"Edit your profile data" } + end ) + + ui.sectionRow( _"All fields are optional. Please enter only data which should be published." ) + + ui.sectionRow( function() + + ui.field.text{ label = _"Organizational unit", name = "organizational_unit", readonly = config.locked_profile_fields.organizational_unit } + ui.field.text{ label = _"Internal posts", name = "internal_posts", readonly = config.locked_profile_fields.internal_posts } + ui.field.text{ label = _"Real name", name = "realname", readonly = config.locked_profile_fields.realname } + ui.field.text{ label = _"Birthday" .. " YYYY-MM-DD ", name = "birthday", attr = { id = "profile_birthday" }, readonly = config.locked_profile_fields.birthday } + ui.script{ static = "gregor.js/gregor.js" } + util.gregor("profile_birthday", "document.getElementById('timeline_search_date').form.submit();") + ui.field.text{ label = _"Address", name = "address", multiline = true, readonly = config.locked_profile_fields.address } + ui.field.text{ label = _"email", name = "email", readonly = config.locked_profile_fields.email } + ui.field.text{ label = _"xmpp", name = "xmpp_address", readonly = config.locked_profile_fields.xmpp_address } + ui.field.text{ label = _"Website", name = "website", readonly = config.locked_profile_fields.website } + ui.field.text{ label = _"Phone", name = "phone", readonly = config.locked_profile_fields.phone } + ui.field.text{ label = _"Mobile phone", name = "mobile_phone", readonly = config.locked_profile_fields.mobile_phone } + ui.field.text{ label = _"Profession", name = "profession", readonly = config.locked_profile_fields.profession } + ui.field.text{ label = _"External memberships", name = "external_memberships", multiline = true, readonly = config.locked_profile_fields.external_memberships } + ui.field.text{ label = _"External posts", name = "external_posts", multiline = true, readonly = config.locked_profile_fields.external_posts } - ui.field.select{ - label = _"Wiki engine for statement", - name = "formatting_engine", - foreign_records = { - { id = "rocketwiki", name = "RocketWiki" }, - { id = "compat", name = _"Traditional wiki syntax" } - }, - attr = {id = "formatting_engine"}, - foreign_id = "id", - foreign_name = "name", - value = param.get("formatting_engine") - } - ui.tag{ - tag = "div", - content = function() - ui.tag{ - tag = "label", - attr = { class = "ui_field_label" }, - content = function() slot.put(" ") end, + if not config.enforce_formatting_engine then + ui.field.select{ + label = _"Wiki engine for statement", + name = "formatting_engine", + foreign_records = config.formatting_engines, + attr = {id = "formatting_engine"}, + foreign_id = "id", + foreign_name = "name", + value = param.get("formatting_engine") + } + ui.tag{ + tag = "div", + content = function() + ui.tag{ + tag = "label", + attr = { class = "ui_field_label" }, + content = function() slot.put(" ") end, + } + ui.tag{ + content = function() + ui.link{ + text = _"Syntax help", + module = "help", + view = "show", + id = "wikisyntax", + attr = {onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} + } + slot.put(" ") + ui.link{ + text = _"(new window)", + module = "help", + view = "show", + id = "wikisyntax", + attr = {target = "_blank", onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} + } + end + } + end + } + end + ui.field.text{ + label = _"Statement", + name = "statement", + multiline = true, + attr = { style = "height: 50ex;" }, + value = param.get("statement") } - ui.tag{ - content = function() - ui.link{ - text = _"Syntax help", - module = "help", - view = "show", - id = "wikisyntax", - attr = {onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} - } - slot.put(" ") - ui.link{ - text = _"(new window)", - module = "help", - view = "show", - id = "wikisyntax", - attr = {target = "_blank", onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} - } - end - } - end - } - ui.field.text{ - label = _"Statement", - name = "statement", - multiline = true, - attr = { style = "height: 50ex;" }, - value = param.get("statement") - } - - - ui.submit{ value = _"Save" } + slot.put("
") + ui.container{ attr = { class = "actions" }, content = function() + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"publish profile data" + }, + content = "" + } + slot.put("


") + ui.link{ + content = _"cancel", + module = "member", view = "show", id = app.session.member.id + } + end } + end ) + end ) end } \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/edit_images.lua --- a/app/main/member/edit_images.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/edit_images.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,11 +1,15 @@ -ui.title(_"Upload images") +ui.titleMember(_"avatar/photo") -util.help("member.edit_images", _"Images") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} ui.form{ record = app.session.member, attr = { - class = "vertical", + class = "vertical section", enctype = 'multipart/form-data' }, module = "member", @@ -19,24 +23,52 @@ } }, content = function() - execute.view{ - module = "member_image", - view = "_show", - params = { - member = app.session.member, - image_type = "avatar" + ui.sectionHead( function() + ui.heading { level = 1, content = _"Upload avatar/photo" } + end ) + ui.sectionRow( function() + execute.view{ + module = "member_image", + view = "_show", + params = { + class = "right", + member = app.session.member, + image_type = "avatar" + } } - } - ui.field.image{ field_name = "avatar", label = _"Avatar" } - execute.view{ - module = "member_image", - view = "_show", - params = { - member = app.session.member, - image_type = "photo" + ui.heading { level = 2, content = _"Avatar"} + ui.container { content = _"Your avatar is a small photo, which will be shown always next to your name." } + slot.put("
") + ui.field.image{ field_name = "avatar" } + slot.put("

") + execute.view{ + module = "member_image", + view = "_show", + params = { + class = "right", + member = app.session.member, + image_type = "photo" + } } - } - ui.field.image{ field_name = "photo", label = _"Photo" } - ui.submit{ value = _"Save" } + ui.heading { level = 2, content = _"Photo"} + ui.container { content = _"Your photo will be shown in your profile." } + slot.put("
") + ui.field.image{ field_name = "photo" } + slot.put("
") + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"publish avatar/photo" + }, + content = "" + } + slot.put("


") + ui.link{ + content = _"cancel", + module = "member", view = "show", id = app.session.member.id + } + end ) end } \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/history.lua --- a/app/main/member/history.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/history.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,76 +1,72 @@ local member = Member:by_id(param.get_id()) -slot.select("head", function() - ui.container{ - attr = { class = "title" }, - content = _("Member name history for '#{name}'", { name = member.name }) - } - ui.container{ attr = { class = "actions" }, content = function() - ui.link{ +ui.titleMember(member) + +ui.section( function() + + ui.sectionHead( function() + ui.heading{ level = 1, content = _"Account history" } + end) + + ui.sectionRow( function() + ui.form{ + attr = { class = "vertical" }, content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Back") - end, - module = "member", - view = "show", - id = member.id + ui.field.text{ label = _"Current name", value = member.name } + ui.field.text{ label = _"Current status", value = member.active and _'activated' or _'deactivated' } + end } - end } -end) - -ui.form{ - attr = { class = "vertical" }, - content = function() - ui.field.text{ label = _"Current name", value = member.name } - ui.field.text{ label = _"Current status", value = member.active and _'activated' or _'deactivated' } - end -} -local entries = member:get_reference_selector("history_entries"):add_order_by("id DESC"):exec() - -ui.tag{ - tag = "table", - content = function() - ui.tag{ - tag = "tr", - content = function() - ui.tag{ - tag = "th", - content = _("Name") - } - ui.tag{ - tag = "th", - content = _("Status") - } - ui.tag{ - tag = "th", - content = _("until") - } - end - } - for i, entry in ipairs(entries) do + local entries = member:get_reference_selector("history_entries"):add_order_by("id DESC"):exec() + + if #entries > 0 then ui.tag{ - tag = "tr", + tag = "table", content = function() ui.tag{ - tag = "td", - content = entry.name + tag = "tr", + content = function() + ui.tag{ + tag = "th", + content = _("Name") + } + ui.tag{ + tag = "th", + content = _("Status") + } + ui.tag{ + tag = "th", + content = _("until") + } + end } - ui.tag{ - tag = "td", - content = entry.active and _'activated' or _'deactivated', - } - ui.tag{ - tag = "td", - content = format.timestamp(entry["until"]) - } + for i, entry in ipairs(entries) do + ui.tag{ + tag = "tr", + content = function() + ui.tag{ + tag = "td", + content = entry.name + } + ui.tag{ + tag = "td", + content = entry.active and _'activated' or _'deactivated', + } + ui.tag{ + tag = "td", + content = format.timestamp(entry["until"]) + } + end + } + end end } end - end -} -slot.put("
") -ui.container{ - content = _("This member account has been created at #{created}", { created = format.timestamp(member.activated)}) -} + slot.put("
") + ui.container{ + content = _("This member account has been created at #{created}", { created = format.timestamp(member.activated)}) + } + end) + +end) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/list.lua --- a/app/main/member/list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,12 +1,19 @@ -slot.put_into("title", _"Member list") - -util.help("member.list") +ui.title(_"Member list") local members_selector = Member:new_selector() :add_where("activated NOTNULL") -execute.view{ - module = "member", - view = "_list", - params = { members_selector = members_selector } -} +ui.section( function() + + ui.sectionHead( function() + ui.heading { level = 1, content = _"Member list" } + end ) + + ui.sectionRow( function() + execute.view{ + module = "member", + view = "_list", + params = { members_selector = members_selector } + } + end ) +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/settings.lua --- a/app/main/member/settings.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -ui.title(_"Settings") - -local pages = {} - -if not config.locked_profile_fields.name then - pages[#pages+1] = { view = "settings_name", text = _"Change your screen name" } -end -if not config.locked_profile_fields.login then - pages[#pages+1] = { view = "settings_login", text = _"Change your login" } -end -pages[#pages+1] = { view = "settings_password", text = _"Change your password" } -if not config.locked_profile_fields.notify_email then - pages[#pages+1] = { view = "settings_email", text = _"Change your notification email address" } -end -pages[#pages+1] = { view = "settings_notification", text = _"Notification settings" } -pages[#pages+1] = { view = "developer_settings", text = _"Developer settings" } - -if config.download_dir then - pages[#pages+1] = { module = "index", view = "download", text = _"Database download" } -end - -ui.list{ - attr = { class = "menu_list" }, - style = "ulli", - records = pages, - columns = { - { - content = function(page) - ui.link{ - module = page.module or "member", - view = page.view, - text = page.text - } - end - } - } -} - diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/settings_email.lua --- a/app/main/member/settings_email.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/settings_email.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,6 +1,10 @@ -ui.title(_"Change your notification email address") +ui.titleMember(_"Email address") -util.help("member.settings.email_address", _"Change email") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} ui.form{ attr = { class = "vertical" }, @@ -9,19 +13,47 @@ routing = { ok = { mode = "redirect", - module = "index", - view = "index" + module = "member", + view = "show", + id = app.session.member_id } }, content = function() - if app.session.member.notify_email then - ui.field.text{ label = _"Confirmed address", value = app.session.member.notify_email, readonly = true } - end - if app.session.member.notify_email_unconfirmed then - ui.field.text{ label = _"Unconfirmed address", value = app.session.member.notify_email_unconfirmed, readonly = true } - end - ui.field.text{ label = _"New address", name = "email" } - ui.submit{ value = _"Change email" } + ui.section( function() + + ui.sectionHead( function() + ui.heading { level = 1, content = _"Email address for notifications" } + end ) + + ui.sectionRow( function() + if app.session.member.notify_email then + ui.field.text{ label = _"confirmed address", value = app.session.member.notify_email, readonly = true } + end + if app.session.member.notify_email_unconfirmed then + ui.field.text{ label = _"unconfirmed address", value = app.session.member.notify_email_unconfirmed, readonly = true } + end + if app.session.member.notify_email or app.session.member.notify_email_unconfirmed then + slot.put("
") + end + ui.heading { level = 2, content = _"Enter a new email address:" } + ui.field.text{ name = "email" } + slot.put("
") + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Save" + }, + content = "" + } + slot.put("


") + ui.link{ + content = _"Cancel", + module = "member", view = "show", id = app.session.member.id + } + end ) + end ) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/settings_login.lua --- a/app/main/member/settings_login.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/settings_login.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,21 +1,52 @@ -ui.title(_"Change your login") +ui.titleMember(_"login name") -util.help("member.settings.login", _"Change login") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} ui.form{ - attr = { class = "vertical" }, + attr = { class = "wide" }, module = "member", action = "update_login", routing = { ok = { mode = "redirect", - module = "index", - view = "index" + module = "member", + view = "show", + id = app.session.member_id } }, content = function() - ui.field.text{ label = _"Login", name = "login", value = app.session.member.login } - ui.submit{ value = _"Change login" } + ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = _"Login name" } + end ) + + ui.sectionRow( function() + ui.heading { level = 2, content = _"Enter a new login name" } + ui.field.text{ name = "login", value = app.session.member.login } + + slot.put("
") + + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Save" + }, + content = "" + } + slot.put("


") + + ui.link { + module = "member", view = "show", id = app.session.member_id, + content = _"Cancel" + } + end ) + end ) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/settings_name.lua --- a/app/main/member/settings_name.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/settings_name.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,20 +1,50 @@ -ui.title(_"Change your screen name") +ui.titleMember(_"Screen name") -util.help("member.settings.name", _"Change name") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} ui.form{ - attr = { class = "vertical" }, + attr = { class = "wide" }, module = "member", action = "update_name", routing = { ok = { mode = "redirect", - module = "index", - view = "index" + module = "member", + view = "show", + id = app.session.member_id } }, content = function() - ui.field.text{ label = _"Name", name = "name", value = app.session.member.name } - ui.submit{ value = _"Change name" } + ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = _"Screen name" } + end ) + + ui.sectionRow( function() + ui.heading { level = 2, content = _"Enter a new screen name:" } + ui.field.text{ name = "name", value = app.session.member.name } + + slot.put("
") + + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Save" + }, + content = "" + } + slot.put("


") + ui.link { + module = "member", view = "show", id = app.session.member_id, + content = _"Cancel" + } + end ) + end ) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/settings_notification.lua --- a/app/main/member/settings_notification.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/settings_notification.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,6 +1,12 @@ -ui.title(_"Notification settings") +local return_to = param.get("return_to") + +ui.titleMember("notification settings") -util.help("member.settings.notification", _"Notification settings") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} ui.form{ attr = { class = "vertical" }, @@ -9,99 +15,138 @@ routing = { ok = { mode = "redirect", - module = "index", - view = "index" + module = return_to == "home" and "index" or "member", + view = return_to == "home" and "index" or "show", + id = return_to ~= "home" and app.session.member_id or nil } }, content = function() - ui.tag{ tag = "p", content = _"I like to receive notifications by email about events in my areas and issues:" } - - ui.container{ content = function() - ui.tag{ - tag = "input", - attr = { - id = "notify_level_none", - type = "radio", name = "notify_level", value = "none", - checked = app.session.member.notify_level == 'none' and "checked" or nil - } - } - ui.tag{ - tag = "label", attr = { ['for'] = "notify_level_none" }, - content = _"No notifications at all" - } - end } - - slot.put("
") - - ui.container{ content = function() - ui.tag{ - tag = "input", - attr = { - id = "notify_level_all", - type = "radio", name = "notify_level", value = "all", - checked = app.session.member.notify_level == 'all' and "checked" or nil - } - } - ui.tag{ - tag = "label", attr = { ['for'] = "notify_level_all" }, - content = _"All of them" - } - end } + + ui.section( function() + + ui.sectionHead( function() + ui.heading { level = 1, content = _"For which issue phases do you like to receive notification emails?" } + end ) + - slot.put("
") + ui.sectionRow( function() + + ui.container{ content = function() + ui.tag{ + tag = "input", + attr = { + id = "notify_level_all", + type = "radio", name = "notify_level", value = "all", + checked = app.session.member.notify_level == 'all' and "checked" or nil + } + } + ui.tag{ + tag = "label", attr = { ['for'] = "notify_level_all" }, + content = _"I like to receive notifications" + } + end } + + slot.put("
") + + ui.container{ content = function() + ui.tag{ + tag = "input", + attr = { + id = "notify_level_discussion", + type = "radio", name = "notify_level", value = "discussion", + checked = app.session.member.notify_level == 'discussion' and "checked" or nil + } + } + ui.tag{ + tag = "label", attr = { ['for'] = "notify_level_discussion" }, + content = _"Only for issues reaching the discussion phase" + } + end } + + slot.put("
") - ui.container{ content = function() - ui.tag{ - tag = "input", - attr = { - id = "notify_level_discussion", - type = "radio", name = "notify_level", value = "discussion", - checked = app.session.member.notify_level == 'discussion' and "checked" or nil + ui.container{ content = function() + ui.tag{ + tag = "input", + attr = { + id = "notify_level_verification", + type = "radio", name = "notify_level", value = "verification", + checked = app.session.member.notify_level == 'verification' and "checked" or nil + } + } + ui.tag{ + tag = "label", attr = { ['for'] = "notify_level_verification" }, + content = _"Only for issues reaching the verification phase" + } + end } + + slot.put("
") + + ui.container{ content = function() + ui.tag{ + tag = "input", + attr = { + id = "notify_level_voting", + type = "radio", name = "notify_level", value = "voting", + checked = app.session.member.notify_level == 'voting' and "checked" or nil + } + } + ui.tag{ + tag = "label", attr = { ['for'] = "notify_level_voting" }, + content = _"Only for issues reaching the voting phase" + } + end } + + slot.put("
") + + ui.container{ content = function() + ui.tag{ + tag = "input", + attr = { + id = "notify_level_none", + type = "radio", name = "notify_level", value = "none", + checked = app.session.member.notify_level == 'none' and "checked" or nil + } + } + ui.tag{ + tag = "label", attr = { ['for'] = "notify_level_none" }, + content = _"I do not like to receive notifications by email" + } + end } + + slot.put("
") + + ui.container { content = _"Notifications are only send to you about events in the subject areas you subscribed, the issues you are interested in and the initiatives you are supporting." } + + + slot.put("
") + + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Save" + }, + content = "" } - } - ui.tag{ - tag = "label", attr = { ['for'] = "notify_level_discussion" }, - content = _"Only for issues reaching the discussion phase" - } - end } - - slot.put("
") - - ui.container{ content = function() - ui.tag{ - tag = "input", - attr = { - id = "notify_level_verification", - type = "radio", name = "notify_level", value = "verification", - checked = app.session.member.notify_level == 'verification' and "checked" or nil - } - } - ui.tag{ - tag = "label", attr = { ['for'] = "notify_level_verification" }, - content = _"Only for issues reaching the frozen phase" - } - end } + slot.put("


") + + slot.put(" ") + if return_to == "home" then + ui.link { + module = "index", view = "index", + content = _"cancel" + } + else + ui.link { + module = "member", view = "show", id = app.session.member_id, + content = _"cancel" + } + end + end ) + end ) - slot.put("
") - - ui.container{ content = function() - ui.tag{ - tag = "input", - attr = { - id = "notify_level_voting", - type = "radio", name = "notify_level", value = "voting", - checked = app.session.member.notify_level == 'voting' and "checked" or nil - } - } - ui.tag{ - tag = "label", attr = { ['for'] = "notify_level_voting" }, - content = _"Only for issues reaching the voting phase" - } - end } - - slot.put("
") - - ui.submit{ value = _"Change notification settings" } end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/settings_password.lua --- a/app/main/member/settings_password.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/settings_password.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,22 +1,58 @@ -ui.title(_"Change your password") +ui.titleMember(_"Password") -util.help("member.settings.password", _"Change password") +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = app.session.member + } +} ui.form{ - attr = { class = "vertical" }, + attr = { class = "wide" }, module = "member", action = "update_password", routing = { ok = { mode = "redirect", - module = "index", - view = "index" + module = "member", + view = "show", + id = app.session.member_id } }, 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" } + ui.section( function() + ui.sectionHead( function() + ui.heading { level = 1, content = _"Password" } + end ) + + ui.sectionRow( function() + ui.heading { level = 2, content = _"Enter your current password:" } + ui.field.password{ name = "old_password" } + + slot.put("
") + + ui.heading { level = 2, content = _"Enter a new password:" } + ui.field.password{ name = "new_password1" } + + ui.heading { level = 2, content = _"Enter your new password again please:" } + ui.field.password{ name = "new_password2" } + + slot.put("
") + + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + value = _"Save" + }, + content = "" + } + slot.put("


") + ui.link { + module = "member", view = "show", id = app.session.member_id, + content = _"Cancel" + } + end ) + end ) end } \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/member/show.lua --- a/app/main/member/show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/member/show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,150 +1,185 @@ local member = Member:by_id(param.get_id()) if not member or not member.activated then - error("access denied") + execute.view { module = "index", view = "404" } + request.set_status("404 Not Found") + return end +local limit = 25 + +local initiated_initiatives = Initiative:new_selector() + :join("initiator", nil, { "initiator.initiative_id = initiative.id and initiator.member_id = ?", member.id }) + :join("issue", nil, "issue.id = initiative.issue_id") + :add_where("issue.closed ISNULL") + :add_order_by("initiative.id DESC") + :limit(limit+1) + :exec() + +initiated_initiatives:load("issue") +initiated_initiatives:load_everything_for_member_id(member.id) + +local supported_initiatives = Initiative:new_selector() + :join("supporter", nil, { "supporter.initiative_id = initiative.id and supporter.member_id = ?", member.id }) + :join("issue", nil, "issue.id = initiative.issue_id") + :add_where("issue.closed ISNULL") + :add_order_by("initiative.id DESC") + :limit(limit+1) + :exec() + +supported_initiatives:load("issue") +supported_initiatives:load_everything_for_member_id(member.id) + +local voted_initiatives = Initiative:new_selector() + :add_where("initiative.rank = 1") + :join("direct_voter", nil, { "direct_voter.issue_id = initiative.issue_id and direct_voter.member_id = ?", member.id }) + :join("vote", nil, { "vote.initiative_id = initiative.id and vote.member_id = ?", member.id }) + :join("issue", nil, "issue.id = initiative.issue_id") + :add_order_by("issue.closed DESC, initiative.id DESC") + :add_field("vote.grade", "vote_grade") + :add_field("vote.first_preference", "vote_first_preference") + :limit(limit+1) + :exec() + +voted_initiatives:load("issue") +voted_initiatives:load_everything_for_member_id(member.id) + +local incoming_delegations_selector = member:get_reference_selector("incoming_delegations") + :left_join("issue", "_member_showtab_issue", "_member_showtab_issue.id = delegation.issue_id AND _member_showtab_issue.closed ISNULL") + :add_where("_member_showtab_issue.closed ISNULL") + :add_order_by("delegation.unit_id, delegation.area_id, delegation.issue_id") + :limit(limit+1) + +local outgoing_delegations_selector = member:get_reference_selector("outgoing_delegations") + :left_join("issue", "_member_showtab_issue", "_member_showtab_issue.id = delegation.issue_id AND _member_showtab_issue.closed ISNULL") + :add_where("_member_showtab_issue.closed ISNULL") + :add_order_by("delegation.unit_id, delegation.area_id, delegation.issue_id") + :limit(limit+1) + + app.html_title.title = member.name app.html_title.subtitle = _("Member") -slot.select("head", function() - ui.container{ - attr = { class = "title" }, - content = _("Member '#{member}'", { member = member.name }) +ui.titleMember(member) + +execute.view { + module = "member", view = "_sidebar_whatcanido", params = { + member = member } - - ui.container{ attr = { class = "actions" }, content = function() +} - if member.id == app.session.member_id then - ui.link{ - content = function() - slot.put(encode.html(_"Edit profile")) - end, - module = "member", - view = "edit" +execute.view { + module = "member", view = "_sidebar_contacts", params = { + member = member + } +} + + +ui.section( function() + ui.sectionHead( function() + execute.view{ + module = "member_image", + view = "_show", + params = { + member = member, + image_type = "avatar", + show_dummy = true, + class = "left" } - slot.put(" · ") - ui.link{ - content = function() - slot.put(encode.html(_"Upload avatar/photo")) - end, - module = "member", - view = "edit_images" - } - slot.put(" · ") - end - ui.link{ + } + ui.heading{ level = 1, content = member.name } + slot.put("
") + ui.container { + attr = { class = "right" }, content = function() - slot.put(encode.html(_"Show member history")) - end, - module = "member", - view = "history", - id = member.id + ui.link{ + content = _"Account history", + module = "member", view = "history", id = member.id + } + end } - if not member.active then - slot.put(" · ") - ui.tag{ - attr = { class = "interest deactivated_member_info" }, - content = _"This member is inactive" - } + if member.identification then + ui.container{ content = member.identification } end - if member.locked then - slot.put(" · ") - ui.tag{ - attr = { class = "interest deactivated_member_info" }, - content = _"This member is locked" + end ) + ui.sectionRow( function() + execute.view{ + module = "member", + view = "_profile", + params = { member = member } + } + end ) +end ) + + +ui.section( function() + ui.sectionHead( function() + ui.heading { level = 2, content = _"Initiatives created by this member" } + end ) + ui.sectionRow( function() + for i, initiative in ipairs(initiated_initiatives) do + execute.view { + module = "initiative", view = "_list", + params = { initiative = initiative }, + member = member } end - if app.session.member_id and not (member.id == app.session.member.id) then - slot.put(" · ") - --TODO performance - local contact = Contact:by_pk(app.session.member.id, member.id) - if contact then - ui.link{ - text = _"Remove from contacts", - module = "contact", - action = "remove_member", - id = contact.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() - } - } - } - elseif member.activated then - ui.link{ - text = _"Add to my contacts", - module = "contact", - action = "add_member", - id = 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 ) + +ui.section( function() + ui.sectionHead( function() + ui.heading { level = 2, content = _"What this member is currently supporting" } + end ) + ui.sectionRow( function() + for i, initiative in ipairs(supported_initiatives) do + execute.view { + module = "initiative", view = "_list", + params = { initiative = initiative }, + member = member + } + end + end ) +end ) + +ui.section( function() + ui.sectionHead( function() + ui.heading { level = 2, content = _"How this member voted" } + end ) + ui.sectionRow( function() + for i, initiative in ipairs(voted_initiatives) do + execute.view { + module = "initiative", view = "_list", + params = { initiative = initiative } + } end - if app.session.member_id then - local ignored_member = IgnoredMember:by_pk(app.session.member.id, member.id) - slot.put(" · ") - if ignored_member then - ui.tag{ - attr = { class = "interest" }, - content = _"You have ignored this member" - } - slot.put(" · ") - ui.link{ - text = _"Stop ignoring member", - module = "member", - action = "update_ignore_member", - id = member.id, - params = { delete = true }, - routing = { - default = { - mode = "redirect", - module = request.get_module(), - view = request.get_view(), - id = param.get_id_cgi(), - params = param.get_all_cgi() - } - } - } - elseif member.activated then - ui.link{ - attr = { class = "interest" }, - text = _"Ignore member", - module = "member", - action = "update_ignore_member", - id = 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 } -end) + end ) +end ) + -util.help("member.show", _"Member page") +ui.section( function() + ui.sectionHead( function() + ui.heading { level = 2, content = _"Outgoing delegations" } + end ) + ui.sectionRow( function() + execute.view { + module = "delegation", view = "_list", + params = { delegations_selector = outgoing_delegations_selector, outgoing = true }, + } + end ) +end ) + -execute.view{ - module = "member", - view = "_show", - params = { member = member } -} - +ui.section( function() + + ui.sectionHead( function() + ui.heading { level = 2, content = _"Incoming delegations" } + end ) + ui.sectionRow( function() + execute.view { + module = "delegation", view = "_list", + params = { delegations_selector = incoming_delegations_selector, incoming = true }, + } + end ) + +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/membership/_action/update.lua --- a/app/main/membership/_action/update.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/membership/_action/update.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,26 +1,26 @@ 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) +local area = Area:by_id(area_id) if param.get("delete", atom.boolean) then if membership then membership:destroy() - --slot.put_into("notice", _"Membership removed") + slot.put_into("notice", _"Subscription removed") else - --slot.put_into("notice", _"Membership not existent") + slot.put_into("notice", _"Subscription already removed") end return end +if not app.session.member:has_voting_right_for_unit_id(area.unit_id) then + slot.put_into("error", _"You are not eligible to participate") + return false +end + if not membership then - local area = Area:by_id(area_id) - if not app.session.member:has_voting_right_for_unit_id(area.unit_id) then - error("access denied") - end membership = Membership:new() membership.area_id = area_id membership.member_id = app.session.member_id + membership:save() + slot.put_into("notice", _"Subject area subscribed") end - -membership:save() - ---slot.put_into("notice", _"Membership updated") diff -r a6c7bf07badb -r 701a5cf6b067 app/main/opinion/_action/update.lua --- a/app/main/opinion/_action/update.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/opinion/_action/update.lua Thu Jul 10 01:19:48 2014 +0200 @@ -6,6 +6,10 @@ local suggestion = Suggestion:by_id(suggestion_id) +local degree = param.get("degree", atom.number) +local fulfilled = param.get("fulfilled", atom.boolean) + + if not suggestion then slot.put_into("error", _"This suggestion has been meanwhile deleted") return false @@ -28,7 +32,7 @@ return false end -if param.get("delete") then +if degree == 0 then if opinion then opinion:destroy() end @@ -36,9 +40,6 @@ return end -local degree = param.get("degree", atom.number) -local fulfilled = param.get("fulfilled", atom.boolean) - if degree ~= 0 and not app.session.member:has_voting_right_for_unit_id(suggestion.initiative.issue.area.unit_id) then error("access denied") end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/policy/_list.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/policy/_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,90 @@ +local for_area = param.get("for_area", "table") + +local selector = Policy:new_selector() + :add_where("policy.active") + :add_order_by("policy.index") + +if for_area then + selector:join("allowed_policy", nil, + { "allowed_policy.policy_id = policy.id AND allowed_policy.area_id = ?", for_area.id } + ) +end + +local policies = selector:exec() + + +for i, policy in ipairs(policies) do + ui.container { + attr = { class = "sidebarRow", id = "policy" .. policy.id }, + content = function () + + ui.heading { level = 3, content = policy.name } + + ui.tag{ + content = policy.description + } + + slot.put ( "
" ) + + ui.link { + attr = { + class = "policy-show-details", + onclick = "$('#policy" .. policy.id .. " .policy-details').show(); $('#policy" .. policy.id .. " .policy-show-details').hide(); $('#policy" .. policy.id .. " .policy-hide-details').show(); return false;" + }, + content = _"show details" + } + + ui.link { + attr = { + class = "policy-hide-details", + onclick = "$('#policy" .. policy.id .. " .policy-details').hide(); $('#policy" .. policy.id .. " .policy-show-details').show(); $('#policy" .. policy.id .. " .policy-hide-details').hide(); return false;", + style = "display: none;" + }, + content = _"hide details" + } + + ui.container { + attr = { + class = "policy-details", + style = "display: none;" + }, + content = function () + + ui.heading { level = 4, content = _"Phase durations" } + + if policy.polling then + ui.field.text{ label = _"New" .. ":", value = _"without" } + else + ui.field.text{ label = _"New" .. ":", value = "≤ " .. policy.admission_time } + end + ui.field.text{ label = _"Discussion" .. ":", value = policy.discussion_time or _"variable" } + ui.field.text{ label = _"Frozen" .. ":", value = policy.verification_time or _"variable" } + ui.field.text{ label = _"Voting" .. ":", value = policy.voting_time or _"variable" } + + ui.heading { level = 4, content = _"Quorums" } + + if policy.polling then + ui.field.text{ label = _"Issue quorum" .. ":", value = _"without" } + else + ui.field.text{ + label = _"Issue quorum" .. ":", + value = "≥ " .. tostring(policy.issue_quorum_num) .. "/" .. tostring(policy.issue_quorum_den) + } + end + ui.field.text{ + label = _"Initiative quorum" .. ":", + value = "≥ " .. tostring(policy.initiative_quorum_num) .. "/" .. tostring(policy.initiative_quorum_den) + } + ui.field.text{ + label = _"Direct majority" .. ":", + value = (policy.direct_majority_strict and ">" or "≥" ) .. " " .. tostring(policy.direct_majority_num) .. "/" .. tostring(policy.direct_majority_den) + } + ui.field.text{ + label = _"Indirect majority" .. ":", + value = (policy.indirect_majority_strict and ">" or "≥" ) .. " " .. tostring(policy.indirect_majority_num) .. "/" .. tostring(policy.indirect_majority_den) + } + end + } + end + } +end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/policy/list.lua --- a/app/main/policy/list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/policy/list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,73 +1,3 @@ ui.title(_"Policies") -util.help("policy.list", _"Policies") -local policies = Policy:new_selector() - :add_where("active") - :add_order_by("index") - :exec() - -ui.list{ - records = policies, - columns = { - { - label_attr = { width = "500" }, - label = _"Policy", - content = function(policy) - ui.link{ - module = "policy", view = "show", id = policy.id, - attr = { style = "font-weight: bold" }, - content = function() - slot.put(encode.html(policy.name)) - if not policy.active then - slot.put(" (", _"disabled", ")") - end - end - } - ui.tag{ - tag = "div", - content = policy.description - } - end - }, - { - label_attr = { width = "200" }, - label = _"Phases", - content = function(policy) - if policy.polling then - ui.field.text{ label = _"New" .. ":", value = _"without" } - else - ui.field.text{ label = _"New" .. ":", value = "≤ " .. policy.admission_time } - end - ui.field.text{ label = _"Discussion" .. ":", value = policy.discussion_time or _"variable" } - ui.field.text{ label = _"Frozen" .. ":", value = policy.verification_time or _"variable" } - ui.field.text{ label = _"Voting" .. ":", value = policy.voting_time or _"variable" } - end - }, - { - label_attr = { width = "200" }, - label = _"Quorum", - content = function(policy) - if policy.polling then - ui.field.text{ label = _"Issue quorum" .. ":", value = _"without" } - else - ui.field.text{ - label = _"Issue quorum" .. ":", - value = "≥ " .. tostring(policy.issue_quorum_num) .. "/" .. tostring(policy.issue_quorum_den) - } - end - ui.field.text{ - label = _"Initiative quorum" .. ":", - value = "≥ " .. tostring(policy.initiative_quorum_num) .. "/" .. tostring(policy.initiative_quorum_den) - } - ui.field.text{ - label = _"Direct majority" .. ":", - value = (policy.direct_majority_strict and ">" or "≥" ) .. " " .. tostring(policy.direct_majority_num) .. "/" .. tostring(policy.direct_majority_den) - } - ui.field.text{ - label = _"Indirect majority" .. ":", - value = (policy.indirect_majority_strict and ">" or "≥" ) .. " " .. tostring(policy.indirect_majority_num) .. "/" .. tostring(policy.indirect_majority_den) - } - end - }, - } -} \ No newline at end of file +execute.view { module = "policy", view = "_list" } \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/slideshow/_index.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/slideshow/_index.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,64 @@ +local unit = param.get( "unit", "table" ) +local area = param.get( "area", "table" ) + +local args = { + unit_id = unit and unit.id or nil, + area_id = area and area.id or nil +} + +local lastWinner = Initiative:getLastWinner( args ) +local lastLooser = Initiative:getLastLoser( args ) +local nextEndingVoting = Initiative:getNextEndingVoting( args ) +local nextEndingVerification = Initiative:getNextEndingVerification( args ) +local nextEndingDiscussion = Initiative:getNextEndingDiscussion( args ) +local bestInAdmission = Initiative:getBestInAdmission( args ) + +local slides = { } + +if lastWinner then + slides[#slides+1] = { + title = _"Latest approved issue", + initiative = lastWinner + } +end + +if lastLooser then + slides[#slides+1] = { + title = _"Latest disapproved issue", + initiative = lastLooser + } +end + +if nextEndingVoting then + slides[#slides+1] = { + title = _("Voting #{time_info}", { time_info = nextEndingVoting.issue.state_time_text }), + initiative = nextEndingVoting + } +end + +if nextEndingVerification then + slides[#slides+1] = { + title = _("Verification #{time_info}", { time_info = nextEndingVerification.issue.state_time_text }), + initiative = nextEndingVerification + } +end + +if nextEndingDiscussion then + slides[#slides+1] = { + title = _("Discussion #{time_info}", { time_info = nextEndingDiscussion.issue.state_time_text }), + initiative = nextEndingDiscussion + } +end + +if bestInAdmission then + slides[#slides+1] = { + title = _"Best not admitted initiative", + initiative = bestInAdmission + } +end + +execute.view { + module = "slideshow", view = "_slideshow", params = { + slides = slides + } +} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/slideshow/_slideshow.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/slideshow/_slideshow.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,79 @@ +local slides = param.get( "slides", "table" ) + +local show_slides = {} + +for i, slide in ipairs( slides ) do + + if slide.initiative then + show_slides[ #show_slides + 1 ] = slide + end + +end + +slot.select( "slideshow", function () + + ui.container { attr = { class = "slideshow" }, content = function () + + for i, slide in ipairs( show_slides ) do + + if slide.initiative.issue.closed then + view = "finished" + elseif slide.initiative.issue.fully_frozen then + view = "voting" + elseif slide.initiative.issue.half_frozen then + view = "verification" + elseif slide.initiative.issue.admitted then + view = "discussion" + else + view = "admission" + end + + ui.container { attr = { class = "slide slide-" .. i }, content = function () + + if slide.initiative.issue.closed then + util.initiative_pie(slide.initiative, 150) + end + + ui.container { + attr = { class = "slideshowTitle" }, + content = slide.title + } + + execute.view { + module = "initiative", view = "_list_element", params = { + initiative = slide.initiative + } + } + + end } + + end + + + end } + +end ) + +ui.script{ script = [[ + +var slideshowCurrent = 0; +var slideshowCount = ]] .. #show_slides .. [[ ; +function slideshowShowSlide(i) { + $(".slideshow .slide").slideUp(); + $(".slideshow .slide-" + i).slideDown(); + slideshowCurrent = i; +} + +function slideshowShowNext() { + var next = slideshowCurrent + 1; + if (next > slideshowCount) { + next = 1; + } + slideshowShowSlide(next); + window.setTimeout(slideshowShowNext, 7500); +} + +slideshowShowNext(); + + + ]]} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/slideshow/index.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/slideshow/index.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,26 @@ +local unit = param.get( "unit", "table" ) +local area = param.get( "area", "table" ) + +local args = { + unit_id = unit and unit.id or nil, + area_id = area and area.id or nil +} + +local issues = Issue:new_selector():exec() + + +local slides = {} + +for i, issue in ipairs( issues ) do + slides[ #slides+1 ] = { + title = issue.state_name, + initiative = issue.initiatives[1] + } +end + + +execute.view { + module = "slideshow", view = "_slideshow", params = { + slides = slides + } +} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/suggestion/_action/add.lua --- a/app/main/suggestion/_action/add.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/suggestion/_action/add.lua Thu Jul 10 01:19:48 2014 +0200 @@ -18,11 +18,11 @@ return false end -local formatting_engine = param.get("formatting_engine") +local formatting_engine = param.get("formatting_engine") or config.enforce_formatting_engine local formatting_engine_valid = false -for fe, dummy in pairs(config.formatting_engine_executeables) do - if formatting_engine == fe then +for i, fe in ipairs(config.formatting_engines) do + if formatting_engine == fe.id then formatting_engine_valid = true end end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/suggestion/new.lua --- a/app/main/suggestion/new.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/suggestion/new.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,20 +1,5 @@ local initiative_id = param.get("initiative_id") -slot.put_into("title", _"Add new suggestion") - -ui.actions(function() - ui.link{ - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - module = "initiative", - view = "show", - id = initiative_id, - params = { tab = "suggestions" } - } -end) - ui.form{ module = "suggestion", action = "add", @@ -28,76 +13,94 @@ params = { tab = "suggestions" } } }, - attr = { class = "vertical" }, + attr = { class = "section vertical" }, content = function() - local supported = Supporter:by_pk(initiative_id, app.session.member.id) and true or false - if not supported then - ui.field.text{ - attr = { class = "warning" }, - value = _"You are currently not supporting this initiative directly. By adding suggestions to this initiative you will automatically become a potential supporter." - } - end - ui.field.select{ - label = _"Degree", - name = "degree", - foreign_records = { - { id = 1, name = _"should"}, - { id = 2, name = _"must"}, - }, - foreign_id = "id", - foreign_name = "name" - } - ui.field.text{ label = _"Title (80 chars max)", name = "name" } - ui.field.select{ - label = _"Wiki engine", - name = "formatting_engine", - foreign_records = { - { id = "rocketwiki", name = "RocketWiki" }, - { id = "compat", name = _"Traditional wiki syntax" } - }, - attr = {id = "formatting_engine"}, - foreign_id = "id", - foreign_name = "name", - value = param.get("formatting_engine") - } - ui.tag{ - tag = "div", - content = function() - ui.tag{ - tag = "label", - attr = { class = "ui_field_label" }, - content = function() slot.put(" ") end, + + ui.sectionHead( function() + ui.heading { level = 1, content = _"Add a new suggestion for improvement" } + end) + + ui.sectionRow( function() + + local supported = Supporter:by_pk(initiative_id, app.session.member.id) and true or false + if not supported then + ui.field.text{ + attr = { class = "warning" }, + value = _"You are currently not supporting this initiative directly. By adding suggestions to this initiative you will automatically become a potential supporter." + } + end + ui.field.text{ label = _"A short title (80 chars max)", name = "name" } + + if not config.enforce_formatting_engine then + ui.field.select{ + label = _"Wiki engine", + name = "formatting_engine", + foreign_records = config.formatting_engines, + attr = {id = "formatting_engine"}, + foreign_id = "id", + foreign_name = "name", + value = param.get("formatting_engine") } ui.tag{ + tag = "div", content = function() - ui.link{ - text = _"Syntax help", - module = "help", - view = "show", - id = "wikisyntax", - attr = {onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} + ui.tag{ + tag = "label", + attr = { class = "ui_field_label" }, + content = function() slot.put(" ") end, } - slot.put(" ") - ui.link{ - text = _"(new window)", - module = "help", - view = "show", - id = "wikisyntax", - attr = {target = "_blank", onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} + ui.tag{ + content = function() + ui.link{ + text = _"Syntax help", + module = "help", + view = "show", + id = "wikisyntax", + attr = {onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} + } + slot.put(" ") + ui.link{ + text = _"(new window)", + module = "help", + view = "show", + id = "wikisyntax", + attr = {target = "_blank", onClick="this.href=this.href.replace(/wikisyntax[^.]*/g, 'wikisyntax_'+getElementById('formatting_engine').value)"} + } + end } end } end - } - ui.field.text{ - label = _"Description", - name = "content", - multiline = true, - attr = { style = "height: 50ex;" }, - value = param.get("content") - } + + ui.field.text{ + label = _"Describe how the proposal and/or the reasons of the initiative could be improved", + name = "content", + multiline = true, + attr = { style = "height: 50ex;" }, + value = param.get("content") + } - - ui.submit{ text = _"Commit suggestion" } + ui.field.select{ + label = _"How important is your suggestions for you?", + name = "degree", + foreign_records = { + { id = 1, name = _"should be implemented"}, + { id = 2, name = _"must be implemented"}, + }, + foreign_id = "id", + foreign_name = "name" + } + + ui.submit{ text = _"publish suggestion" } + slot.put(" ") + ui.link{ + content = _"cancel", + module = "initiative", + view = "show", + id = initiative_id, + params = { tab = "suggestions" } + } + + end ) end } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/supporter/show_incoming.lua --- a/app/main/supporter/show_incoming.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -local initiative = Initiative:by_id(param.get("initiative_id", atom.integer)) -local issue = initiative.issue -local member = Member:by_id(param.get("member_id", atom.integer)) - -local members_selector = Member:new_selector() - :join("delegating_interest_snapshot", nil, "delegating_interest_snapshot.member_id = member.id") - :join("issue", nil, "issue.id = delegating_interest_snapshot.issue_id") - :add_where{ "delegating_interest_snapshot.issue_id = ?", issue.id } - :add_where{ "delegating_interest_snapshot.event = ?", issue.latest_snapshot_event } - :add_where{ "delegating_interest_snapshot.delegate_member_ids[1] = ?", member.id } - :add_field{ "delegating_interest_snapshot.weight" } - -execute.view{ - module = "member", - view = "_list", - params = { - members_selector = members_selector, - issue = issue, - trustee = member - } -} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/_action/delete_filter.lua --- a/app/main/timeline/_action/delete_filter.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -local timeline_filter = app.session.member:get_setting_map_by_key_and_subkey("timeline_filters", param.get("name")) - -timeline_filter:destroy() \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/_action/save.lua --- a/app/main/timeline/_action/save.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -local id = param.get("id", atom.number) - -local setting_key = "liquidfeedback_frontend_timeline_current_options" -local setting = Setting:by_pk(app.session.member.id, setting_key) -local options_string = setting.value - -local timeline_filter - -local subkey = param.get("name") - -if not subkey or subkey == "" then - slot.put_into("error", _"This name is really too short!") - request.redirect{ - module = "timeline", - view = "save_filter", - } - return -end - -app.session.member:set_setting_map("timeline_filters", subkey, options_string) - -local timeline_params = {} -if options_string then - for event_ident, filter_idents in setting.value:gmatch("(%S+):(%S+)") do - timeline_params["option_" .. event_ident] = true - if filter_idents ~= "*" then - for filter_ident in filter_idents:gmatch("([^\|]+)") do - timeline_params["option_" .. event_ident .. "_" .. filter_ident] = true - end - end - end -end - -local setting_key = "liquidfeedback_frontend_timeline_current_date" -local setting = Setting:by_pk(app.session.member.id, setting_key) - -if setting then - timeline_params.date = setting.value -end - -request.redirect{ - module = "timeline", - view = "index", - params = timeline_params -} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/_action/update.lua --- a/app/main/timeline/_action/update.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -execute.view{ - module = "timeline", - view = "_constants" -} - -local options_string = param.get("options_string") - -if not options_string then - local active_options = "" - for event_ident, event_name in pairs(event_names) do - if param.get("option_" .. event_ident, atom.boolean) then - active_options = active_options .. event_ident .. ":" - local filter_idents = {} - for filter_ident, filter_name in pairs(filter_names) do - if param.get("option_" .. event_ident .. "_" .. filter_ident, atom.boolean) then - filter_idents[#filter_idents+1] = filter_ident - end - end - if #filter_idents > 0 then - active_options = active_options .. table.concat(filter_idents, "|") .. " " - else - active_options = active_options .. "* " - end - end - end - if #active_options > 0 then - options_string = active_options - end -end - -if not options_string then - options_string = "issue_created:* issue_finished_after_voting:* issue_accepted:* issue_voting_started:* suggestion_created:* issue_canceled:* initiative_created:* issue_finished_without_voting:* draft_created:* initiative_revoked:* issue_half_frozen:* " -end - -if param.get_list("option_ignore_area", atom.string) then - options_string = options_string.." ignore_area:"..table.concat(param.get_list("option_ignore_area", atom.string), "|") -end - -local setting_key = "liquidfeedback_frontend_timeline_current_options" -local setting = Setting:by_pk(app.session.member.id, setting_key) - -if not setting or setting.value ~= options_string then - if not setting then - setting = Setting:new() - setting.member_id = app.session.member_id - setting.key = setting_key - end - if options_string then - setting.value = options_string - setting:save() - end -end - -local date = param.get("date") - -if param.get("search_from") == "last_24h" then - date = "last_24h" -end - -if date and #date > 0 then - local setting_key = "liquidfeedback_frontend_timeline_current_date" - local setting = Setting:by_pk(app.session.member.id, setting_key) - if not setting or setting.value ~= date then - if not setting then - setting = Setting:new() - setting.member_id = app.session.member.id - setting.key = setting_key - end - setting.value = date - setting:save() - end -end - -local setting_key = "liquidfeedback_frontend_timeline_current_options" -local setting = Setting:by_pk(app.session.member.id, setting_key) - -local timeline_params = {} -if setting and setting.value then - for event_ident, filter_idents in setting.value:gmatch("(%S+):(%S+)") do - timeline_params["option_" .. event_ident] = true - if filter_idents ~= "*" then - for filter_ident in filter_idents:gmatch("([^\|]+)") do - timeline_params["option_" .. event_ident .. "_" .. filter_ident] = true - end - end - end -end - -local setting_key = "liquidfeedback_frontend_timeline_current_date" -local setting = Setting:by_pk(app.session.member.id, setting_key) - -if setting then - timeline_params.date = setting.value -end - -timeline_params.show_options = param.get("show_options", atom.boolean) - -if param.get("save", atom.boolean) then - request.redirect{ - module = "timeline", - view = "save_filter", - params = { - current_name = param.get("current_name") - } - } -else - request.redirect{ - module = "timeline", - view = "index", - params = timeline_params - } -end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/_constants.lua --- a/app/main/timeline/_constants.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -event_names = { - issue_created = _"New issue", - issue_canceled = _"Issue canceled", - issue_accepted = _"Issue accepted", - issue_half_frozen = _"Issue frozen", - issue_finished_without_voting = _"Issue finished without voting", - issue_voting_started = _"Voting started", - issue_finished_after_voting = _"Issue finished", - initiative_created = _"New initiative", - initiative_revoked = _"Initiative revoked", - draft_created = _"New draft", - suggestion_created = _"New suggestion" -} - -filter_names = { - contact = _"Saved as contact", - interested = _"Interested", - supporter = _"Supported", - potential_supporter = _"Potential supported", - initiator = _"Initiated", - membership = _"Member of area" -} - -option_names = {} -for key, val in pairs(event_names) do - option_names[key] = val -end -for key, val in pairs(filter_names) do - option_names[key] = val -end - diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/_filter/29_filter.lua --- a/app/main/timeline/_filter/29_filter.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -if request.get_view() == "index" and not param.get("date") then - local setting - local setting_key = "liquidfeedback_frontend_timeline_current_options" - if app.session.member_id then - setting = Setting:by_pk(app.session.member.id, setting_key) - end - - local timeline_params = {} - if setting and setting.value then - for event_ident, filter_idents in setting.value:gmatch("(%S+):(%S+)") do - timeline_params["option_" .. event_ident] = true - if filter_idents ~= "*" then - for filter_ident in filter_idents:gmatch("([^\|]+)") do - timeline_params["option_" .. event_ident .. "_" .. filter_ident] = true - end - end - end - end - - local setting - local setting_key = "liquidfeedback_frontend_timeline_current_date" - if app.session.member_id then - setting = Setting:by_pk(app.session.member.id, setting_key) - end - - if setting then - timeline_params.date = setting.value - else - timeline_params.date = "last_24h" - end - - timeline_params.show_options = param.get("show_options", atom.boolean) - - request.redirect{ - module = "timeline", - view = "index", - params = timeline_params - } -else - execute.inner() -end - diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/_list.lua --- a/app/main/timeline/_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -local timeline_selector = param.get("timeline_selector", "table") -local event_names = param.get("event_names", "table") -local initiatives_per_page = param.get("initiatives_per_page", atom.number) or 3 - - --- test if selector is valid -local test_selector = timeline_selector:get_db_conn():new_selector() -test_selector:add_field('count(1)') -test_selector:add_from(timeline_selector) -test_selector:single_object_mode() - -err, x = test_selector:try_exec() - -if err then - slot.put_into("error", _"Invalid query") -else - ui.paginate{ - per_page = param.get("per_page", atom.number) or 25, - selector = timeline_selector, - container_attr = { class = "ui_paginate timeline_results" }, - content = function() - local timelines = timeline_selector:exec() - timelines:load("issue") - timelines:load("initiative") - timelines:load("member") - ui.list{ - attr = { class = "nohover" }, - records = timelines, - columns = { - { - field_attr = { style = "width: 10em;" }, - content = function(timeline) - ui.field.text{ - attr = { style = "font-size: 75%; font-weight: bold; background-color: #ccc; display: block; margin-bottom: 1ex;"}, - value = format.time(timeline.occurrence) - } - - ui.field.text{ - attr = { style = "font-size: 75%; font-weight: bold;"}, - value = event_names[timeline.event] or timeline.event - } - if timeline.event == "draft_created" and timeline.count > 1 then - ui.field.text{ - attr = { style = "font-size: 75%;"}, - value = _("(#{more_count} duplicates removed)", { more_count = timeline.count - 1 }) - } - end - end - }, - { - content = function(timeline) - local issue - local initiative - if timeline.issue then - issue = timeline.issue - elseif timeline.initiative then - initiative = timeline.initiative - issue = initiative.issue - elseif timeline.draft then - initiative = timeline.draft.initiative - issue = initiative.issue - elseif timeline.suggestion then - initiative = timeline.suggestion.initiative - issue = initiative.issue - end - if issue then - if timeline.is_interested then - local label = _"You are interested in this issue", - ui.image{ - attr = { alt = label, title = label, style = "float: left; margin-right: 0.5em;" }, - static = "icons/16/eye.png" - } - end - slot.put(" ") - ui.tag{ - tag = "span", - attr = { style = "font-size: 75%; font-weight: bold; background-color: #ccc; display: block; margin-bottom: 1ex;"}, - content = issue.area.name_with_unit_name .. ", " .. _("Issue ##{id}", { id = issue.id }) - } - else - ui.tag{ - tag = "span", - attr = { style = "font-size: 75%; background-color: #ccc; display: block; margin-bottom: 1ex;"}, - content = function() slot.put(" ") end - } - end - - if timeline.member then - execute.view{ - module = "member_image", - view = "_show", - params = { - member = timeline.member, - image_type = "avatar", - show_dummy = true - } - } - ui.link{ - content = timeline.member.name, - module = "member", - view = "show", - id = timeline.member.id - } - end - if timeline.issue then - local initiatives_selector = timeline.issue - :get_reference_selector("initiatives") - execute.view{ - module = "initiative", - view = "_list", - params = { - issue = timeline.issue, - initiatives_selector = initiatives_selector, - per_page = initiatives_per_page, - no_sort = true, - limit = initiatives_per_page - } - } - elseif initiative then - execute.view{ - module = "initiative", - view = "_list", - params = { - issue = initiative.issue, - initiatives_selector = Initiative:new_selector():add_where{ "initiative.id = ?", initiative.id }, - per_page = initiatives_per_page, - no_sort = true - } - } - end - if timeline.suggestion then - ui.link{ - module = "suggestion", - view = "show", - id = timeline.suggestion.id, - content = timeline.suggestion.name - } - end - end - }, - } - } - end - } -end diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/index.lua --- a/app/main/timeline/index.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,449 +0,0 @@ -execute.view{ - module = "timeline", - view = "_constants" -} - -local active_name = "" -local areas_ignored = {} -local options_box_count = param.get("options_box_count", atom.number) or 1 -if options_box_count > 10 then - options_box_count = 10 -end - -local function format_dow(dow) - local dows = { - _"Monday", - _"Tuesday", - _"Wednesday", - _"Thursday", - _"Friday", - _"Saturday", - _"Sunday" - } - return dows[dow+1] -end -slot.put_into("title", _"Timeline") - -slot.select("actions", function() - local setting_key = "liquidfeedback_frontend_timeline_current_options" - local setting = Setting:by_pk(app.session.member.id, setting_key) - local current_options = "" - if setting then - current_options = setting.value - end - local setting_maps = app.session.member:get_setting_maps_by_key("timeline_filters") - for i, setting_map in ipairs(setting_maps) do - local active - local options_string = setting_map.value - local name = setting_map.subkey - if options_string == current_options then - active = true - active_name = name - end - ui.link{ - image = { static = "icons/16/time.png" }, - attr = { class = active and "action_active" or nil }, - text = name, - form_attr = { class = "inline" }, - module = 'timeline', - action = 'update', - params = { - options_string = options_string - }, - } - end - if #setting_maps > 0 then - ui.link{ - content = function() - ui.image{ static = "icons/16/wrench.png" } - slot.put(_"Manage filter") - end, - module = "timeline", - view = "list_filter", - } - end - ui.link{ - content = function() - ui.image{ static = "icons/16/bullet_disk.png" } - slot.put(_"Save current filter") - end, - module = "timeline", - view = "save_filter", - params = { - current_name = active_name - }, - attr = { - onclick = "el=document.getElementById('timeline_save');el.checked=true;el.form.submit();return(false);" - } - } -end) - -util.help("timeline.index", _"Timeline") - -ui.form{ - module = "timeline", - action = "update", - content = function() - ui.container{ - - content = function() - - ui.tag{ - tag = "input", - attr = { - type = "radio", - id = "timeline_search_last_24h", - name = "search_from", - value = "last_24h", - checked = param.get("date") == "last_24h" and "checked" or nil - }, - } - - ui.tag{ - tag = "label", - attr = { - ["for"] = "timeline_search_last_24h" - }, - content = " " .. _"last 24 hours" .. " " - } - - ui.tag{ - tag = "input", - attr = { - type = "radio", - id = "timeline_search_from_date", - name = "search_from", - value = "date", - checked = not (param.get("date") == "last_24h") and "checked" or nil - }, - } - - slot.put(" ") - local current_date = param.get("date") - if not current_date or #current_date == 0 or current_date == "last_24h" then - current_date = tostring(db:query("select now()::date as date")[1].date) - end - ui.tag{ - tag = "input", - attr = { - type = "text", - id = "timeline_search_date", - style = "width: 10em;", - onchange = "this.form.submit();", - onclick = "document.getElementById('timeline_search_from_date').checked = true;", - name = "date", - value = current_date - }, - content = function() end - } - - ui.script{ static = "gregor.js/gregor.js" } - util.gregor("timeline_search_date", true) - - - ui.link{ - attr = { style = "margin-left: 1em; font-weight: bold;", onclick = "document.getElementById('timeline_search_date').form.submit();return(false);" }, - content = function() - ui.image{ - attr = { style = "margin-right: 0.25em;" }, - static = "icons/16/magnifier.png" - } - slot.put(_"Search") - end, - external = "#", - } - local show_options = param.get("show_options", atom.boolean) - ui.link{ - attr = { style = "margin-left: 1em;", onclick = "el=document.getElementById('timeline_show_options');el.checked=" .. tostring(not show_options) .. ";el.form.submit();return(false);" }, - content = function() - ui.image{ - attr = { style = "margin-right: 0.25em;" }, - static = "icons/16/text_list_bullets.png" - } - slot.put(not show_options and _"Show filter details" or _"Hide filter details") - end, - external = "#", - } - - ui.field.boolean{ - attr = { id = "timeline_show_options", style = "display: none;", onchange="this.form.submit();" }, - name = "show_options", - value = param.get("show_options", atom.boolean) - } - ui.hidden_field{ name = "current_name", value = active_name } - ui.field.boolean{ - attr = { id = "timeline_save", style = "display: none;", onchange="this.form.submit();" }, - name = "save", - value = false - } - - end - } - - ui.container{ - attr = { - id = "timeline_options_boxes", - class = "vertical", - style = not param.get("show_options", atom.boolean) and "display: none;" or nil - }, - content = function() - - local function option_field(event_ident, filter_ident) - local param_name - if not filter_ident then - param_name = "option_" .. event_ident - else - param_name = "option_" .. event_ident .. "_" .. filter_ident - end - local value = param.get(param_name, atom.boolean) - ui.field.boolean{ - attr = { id = param_name }, - name = param_name, - value = value, - } - end - - local function filter_option_fields(event_ident, filter_idents) - - for i, filter_ident in ipairs(filter_idents) do - slot.put("") - option_field(event_ident, filter_ident) - slot.put("
") - ui.tag{ - attr = { ["for"] = "option_" .. event_ident .. "_" .. filter_ident }, - tag = "label", - content = filter_names[filter_ident] - } - slot.put("
") - end - - end - - local event_groups = { - { - title = _"Issue events", - event_idents = { - "issue_created", - "issue_canceled", - "issue_accepted", - "issue_half_frozen", - "issue_finished_without_voting", - "issue_voting_started", - "issue_finished_after_voting", - }, - filter_idents = { - "membership", - "interested" - } - }, - { - title = _"Initiative events", - event_idents = { - "initiative_created", - "initiative_revoked", - "draft_created", - "suggestion_created", - }, - filter_idents = { - "membership", - "interested", - "supporter", - "potential_supporter", - "initiator" - } - } - } - - slot.put("") - - for i_event_group, event_group in ipairs(event_groups) do - slot.put("") - slot.put("") - slot.put("") - local event_idents = event_group.event_idents - for i, event_ident in ipairs(event_idents) do - slot.put("") - filter_option_fields(event_ident, event_group.filter_idents) - slot.put("") - end - end - - slot.put("
") - slot.put(event_group.title) - slot.put("") - slot.put(_"Show only events which match... (or associtated)") - slot.put("
") - option_field(event_ident) - slot.put("
") - ui.tag{ - attr = { ["for"] = "option_" .. event_ident }, - tag = "label", - content = event_names[event_ident] - } - slot.put("
") - - local areas = Area:new_selector():add_where("active='t'"):exec() - for i, area in ipairs(areas) do - if param.get("option_ignore_area_"..tostring(area.id)) then - areas_ignored[#areas_ignored+1] = area.id - end - end - - ui.multiselect{ - style = "checkbox", - selected_ids = areas_ignored, - container_attr = { class = "ignore_area_list" }, - container2_attr = { class = "ignore_area_item" }, - label = _"Ignore Areas", - name = "option_ignore_area[]", - foreign_records = areas, - foreign_id = "id", - foreign_name = "name" - } - - end - } - end -} - -local date = param.get("date") - -if not date or #date == 0 then - date = "today" -end - -local timeline_selector - -for event, event_name in pairs(event_names) do - - if param.get("option_" .. event, atom.boolean) then - - local tmp = Timeline:new_selector() - if event == "draft_created" then - tmp - :reset_fields() - :add_field("max(timeline.occurrence)", "occurrence") - :add_field("timeline.event", nil, { "grouped" }) - :add_field("timeline.issue_id", nil, { "grouped" }) - :add_field("draft.initiative_id", nil, { "grouped" }) - :add_field("max(timeline.draft_id)", "draft_id") - :add_field("timeline.suggestion_id", nil, { "grouped" }) - :add_field("COUNT(*)", "count") - else - tmp - :add_field("1", "count") - end - - if date == "last_24h" then - tmp:add_where{ "occurrence > now() - '24 hours'::interval" } - else - local start,stop = string.gmatch(date, "(%d+-%d+-%d+):(%d+-%d+-%d+)")() - if start and stop then - tmp:add_where{ "occurrence::date >= ?::date AND occurrence::date <= ?::date", start, stop } - else - local age = string.gmatch(date, "age:(.+)")() - if age then - tmp:add_where{ "occurrence >= now() - ?::interval", age } - else - local since = string.gmatch(date, "since:%s*(%d+-%d+-%d+)%s*")() - if since then - tmp:add_where{ "occurrence::date >= ?::date", since } - else - tmp:add_where{ "occurrence::date = ?::date", date } - end - end - end - end - tmp - :left_join("draft", nil, "draft.id = timeline.draft_id") - :left_join("suggestion", nil, "suggestion.id = timeline.suggestion_id") - :left_join("initiative", nil, "initiative.id = timeline.initiative_id or initiative.id = draft.initiative_id or initiative.id = suggestion.initiative_id") - :left_join("issue", nil, "issue.id = timeline.issue_id or issue.id = initiative.issue_id") - :left_join("area", nil, "area.id = issue.area_id") - - :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} ) - :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} ) - :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id} ) - :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} ) - - local group - if event == "draft_created" then - group = { "grouped" } - tmp:add_where{"EXISTS(SELECT 1 from draft as cdraft WHERE draft.initiative_id = cdraft.initiative_id AND cdraft.id != draft.id ORDER BY cdraft.id DESC)"} - end - - tmp - :add_field("(_interest.member_id NOTNULL)", "is_interested", group) - :add_field("(_initiator.member_id NOTNULL)", "is_initiator", group) - :add_field({"(_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_supporter", group) - :add_field({"EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_potential_supporter", group) - -- :left_join("member", nil, "member.id = timeline.member_id", group) - - if #areas_ignored > 0 then - tmp:add_where{"area.id NOT IN ($)", areas_ignored} - end - - tmp:add_where{ "event = ?", event } - - local filters = {} - if param.get("option_" .. event .. "_membership", atom.boolean) then - filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR _membership.member_id NOTNULL" - end - - if param.get("option_" .. event .. "_supporter", atom.boolean) then - filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR ((_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1))" - end - - if param.get("option_" .. event .. "_potential_supporter", atom.boolean) then - filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR ((_supporter.member_id NOTNULL) AND EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1))" - end - - if param.get("option_" .. event .. "_interested", atom.boolean) then - filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR _interest.member_id NOTNULL" - end - - if param.get("option_" .. event .. "_initiator", atom.boolean) then - filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR _initiator.member_id NOTNULL" - end - - if #filters > 0 then - local filter_string = "(" .. table.concat(filters, ") OR (") .. ")" - tmp:add_where{ filter_string, app.session.member.id, app.session.member.id } - end - - if not timeline_selector then - timeline_selector = tmp - else - timeline_selector:union_all(tmp) - end - end -end - -if timeline_selector then - - local initiatives_per_page = param.get("initiatives_per_page", atom.number) - - local outer_timeline_selector = db:new_selector() - outer_timeline_selector._class = Timeline - outer_timeline_selector - :add_field{ "timeline.*" } - :from({"($)", { timeline_selector }}, "timeline" ) - :add_order_by("occurrence DESC") - - slot.put("
") - execute.view{ - module = "timeline", - view = "_list", - params = { - timeline_selector = outer_timeline_selector, - per_page = param.get("per_page", atom.number), - event_names = event_names, - initiatives_per_page = initiatives_per_page - } - } - -else - - slot.put(_"No events selected to list") - -end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/list_filter.lua --- a/app/main/timeline/list_filter.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -slot.put_into("title", _"Manage timeline filters") - -slot.select("actions", function() - ui.link{ - image = { static = "icons/16/cancel.png" }, - text = _"Back to timeline", - module = "timeline", - action = "update" - } -end) - -local timeline_filters = app.session.member:get_setting_maps_by_key("timeline_filters") - -ui.list{ - records = timeline_filters, - columns = { - { - name = "subkey" - }, - { - content = function(timeline_filter) - ui.link{ - attr = { class = "action" }, - text = _"Delete filter", - module = "timeline", - action = "delete_filter", - params = { - name = timeline_filter.subkey - } - } - end - } - } -} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/timeline/save_filter.lua --- a/app/main/timeline/save_filter.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -slot.put_into("title", _"Save timeline filters") - -slot.select("actions", function() - ui.link{ - content = function() - ui.image{ static = "icons/16/cancel.png" } - slot.put(_"Cancel") - end, - module = "timeline", - view = "index" - } -end) - -ui.form{ - attr = { class = "vertical" }, - module = "timeline", - action = "save", - content = function() - ui.field.text{ - label = _"Name", - name = "name", - value = param.get("current_name") - } - ui.submit{ - text = _"Save" - } - end -} diff -r a6c7bf07badb -r 701a5cf6b067 app/main/unit/_head.lua --- a/app/main/unit/_head.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/unit/_head.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,49 +1,32 @@ local unit = param.get("unit", "table") -local member = param.get("member", "table") - -local show_content = param.get("show_content", atom.boolean) -if app.session.member_id then - unit:load_delegation_info_once_for_member_id(app.session.member_id) -end - -ui.container{ attr = { class = "unit_head" }, content = function() +ui.title ( function () - execute.view{ module = "delegation", view = "_info", params = { unit = unit, member = member } } + ui.tag{ attr = { class = "unit" }, content = function() + -- unit link + ui.link { + attr = { class = "unit" }, + content = function() + ui.tag{ attr = { class = "name" }, content = unit.name } + end, + module = "unit", view = "show", + id = unit.id + } - ui.container{ attr = { class = "title" }, content = function() - if not config.single_unit_id then - ui.link{ - module = "unit", view = "show", id = unit.id, - attr = { class = "unit_name" }, content = unit.name + execute.view { + module = "delegation", view = "_info", params = { + unit = unit, member = member } - else - ui.link{ - module = "unit", view = "show", id = unit.id, - attr = { class = "unit_name" }, content = _"LiquidFeedback" .. " · " .. config.instance_name + } + + if config.single_unit_id and not app.session.member_id and config.motd_public then + ui.container{ + attr = { class = "wiki motd" }, + content = function() + slot.put(config.motd_public) + end } end end } - - if show_content then - ui.container{ attr = { class = "content" }, content = function() - - if member and member:has_voting_right_for_unit_id(unit.id) then - if app.session.member_id == member.id then - ui.tag{ content = _"You have voting privileges for this unit" } - slot.put(" · ") - if unit.delegation_info.first_trustee_id == nil then - ui.link{ text = _"Delegate unit", module = "delegation", view = "show", params = { unit_id = unit.id } } - else - ui.link{ text = _"Change unit delegation", module = "delegation", view = "show", params = { unit_id = unit.id } } - end - else - ui.tag{ content = _"Member has voting privileges for this unit" } - end - end - end } - else - slot.put("
") - end - -end } + +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/unit/_list.lua --- a/app/main/unit/_list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/unit/_list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,3 +1,4 @@ +local for_admin = param.get("for_admin", atom.boolean) local units = Unit:get_flattened_tree{ active = true } ui.container{ attr = { class = "box" }, content = function() @@ -11,7 +12,11 @@ for i = 1, unit.depth - 1 do slot.put("     ") end - ui.link{ text = unit.name, module = "unit", view = "show", id = unit.id } + if for_admin then + ui.link{ text = unit.name, module = "admin", view = "unit_edit", id = unit.id } + else + ui.link{ text = unit.name, module = "unit", view = "show", id = unit.id } + end end } } diff -r a6c7bf07badb -r 701a5cf6b067 app/main/unit/_sidebar.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/unit/_sidebar.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,80 @@ +local member = param.get ( "member", "table" ) or app.session.member + +local unit = param.get ( "unit", "table" ) + +local areas_selector = Area:new_selector() + :reset_fields() + :add_field("area.id", nil, { "grouped" }) + :add_field("area.unit_id", nil, { "grouped" }) + :add_field("area.name", nil, { "grouped" }) + :add_where{ "area.unit_id = ?", unit.id } + :add_where{ "area.active" } + :add_order_by("area.name") + +if member then + areas_selector:left_join ( + "membership", nil, + { "membership.area_id = area.id AND membership.member_id = ?", member.id } + ) + areas_selector:add_field("membership.member_id NOTNULL", "subscribed", { "grouped" }) +end + + +local areas = areas_selector:exec() +if member then + unit:load_delegation_info_once_for_member_id(member.id) + areas:load_delegation_info_once_for_member_id(member.id) +end + + +ui.sidebar ( "tab-whatcanido", function () + + ui.sidebarHead( function () + ui.heading { + level = 2, content = _"Subject areas" + } + end ) + + if #areas > 0 then + + ui.container { class = "areas", content = function () + + for i, area in ipairs ( areas ) do + + ui.container { attr = { class = "sidebarRow" }, content = function () + + if member then + local delegation = Delegation:by_pk(member.id, nil, area.id, nil) + + if delegation then + ui.link { + module = "delegation", view = "show", params = { + area_id = area.id + }, + attr = { class = "delegation_info" }, + content = function () + ui.delegation(delegation.trustee_id, delegation.trustee_id and delegation.trustee.name) + end + } + end + end + + if area.subscribed then + ui.image { attr = { class = "icon24 star" }, static = "icons/48/star.png" } + end + + ui.link { + attr = { class = "area" }, + module = "area", view = "show", id = area.id, + content = area.name + } + + end } -- ui.tag "li" + + end -- for i, area + + end } -- ui.tag "ul" + + end -- if #areas > 0 + +end ) -- ui.sidebar \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/unit/_sidebar_members.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/unit/_sidebar_members.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,33 @@ +if not app.session:has_access("all_pseudonymous") then + return +end + +local unit = param.get("unit", "table") +local members_selector = Member:new_selector() + :join("privilege", nil, { "privilege.member_id = member.id AND privilege.unit_id = ? AND privilege.voting_right", unit.id }) + :add_where("active") + :limit(50) + +local member_count = unit.member_count or 0 + +ui.sidebar ( "tab-members", function () + ui.sidebarHead( function () + ui.heading { + level = 2, + content = _("Eligible members (#{count})", { count = member_count }) + } + end ) + execute.view { + module = 'member', view = '_list', params = { + members_selector = members_selector, + no_filter = true, no_paginate = true, + member_class = "sidebarRow sidebarRowNarrow" + } + } + if member_count > members_selector:count() then + ui.link { + text = _"Show all members", + module = "member", view = "list" + } + end +end ) diff -r a6c7bf07badb -r 701a5cf6b067 app/main/unit/_sidebar_whatcanido.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/unit/_sidebar_whatcanido.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,69 @@ +local unit = param.get ( "unit", "table" ) + +ui.sidebar ( "tab-whatcanido", function () + + ui.sidebarHeadWhatCanIDo() + + if app.session.member then + + if app.session.member:has_voting_right_for_unit_id ( unit.id ) then + ui.sidebarSection( function () + + if not unit.delegation_info.first_trustee_id then + ui.heading{ level = 3, content = _"I want to delegate this organizational unit" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + unit_id = unit.id, + }, + content = _("choose delegatee", { + unit_name = unit.name + }) + } + end } + end } + else + ui.container { attr = { class = "right" }, content = function() + local member = Member:by_id(unit.delegation_info.first_trustee_id) + execute.view{ + module = "member_image", + view = "_show", + params = { + member = member, + image_type = "avatar", + show_dummy = true + } + } + end } + ui.heading{ level = 3, content = _"You delegated this unit" } + + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link { + module = "delegation", view = "show", params = { + unit_id = unit.id, + }, + content = _("change/revoke delegation", { + unit_name = unit.name + }) + } + end } + end } + end + end ) + + ui.sidebarSection( function() + ui.heading { level = 3, content = _"I want to start a new initiative" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = _"Open the appropriate subject area where your issue fits in and follow the instruction on that page." } + end } + end ) + + else + ui.sidebarSection( _"You are not entitled to vote in this unit" ) + end + + end + +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/unit/list.lua --- a/app/main/unit/list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/unit/list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,10 +1,10 @@ -slot.put_into("title", _"Unit list") - -util.help("unit.list", _"Unit list") +ui.title(_"Unit list") -slot.put("
") +ui.section( function() + ui.sectionRow( function() + execute.view{ module = "unit", view = "_list" } + end) +end ) -execute.view{ module = "unit", view = "_list" } -slot.put("
") diff -r a6c7bf07badb -r 701a5cf6b067 app/main/unit/show.lua --- a/app/main/unit/show.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/unit/show.lua Thu Jul 10 01:19:48 2014 +0200 @@ -2,19 +2,14 @@ local unit = Unit:by_id(unit_id) -slot.select("head", function() - execute.view{ module = "unit", view = "_head", params = { unit = unit, show_content = true, member = app.session.member } } -end) +if not unit then + execute.view { module = "index", view = "404" } + request.set_status("404 Not Found") + return +end -if config.single_unit_id and not app.session.member_id and config.motd_public then - local help_text = config.motd_public - ui.container{ - attr = { class = "wiki motd" }, - content = function() - slot.put(format.wiki_text(help_text)) - end - } -end + +unit:load_delegation_info_once_for_member_id(app.session.member_id) local areas_selector = Area:build_selector{ active = true, unit_id = unit_id } areas_selector:add_order_by("member_weight DESC") @@ -43,49 +38,38 @@ :add_where("issue.closed NOTNULL") :add_order_by("issue.closed DESC") -local tabs = { - module = "unit", - view = "show", - id = unit.id -} + -tabs[#tabs+1] = { - name = "areas", - label = _"Areas", - module = "area", - view = "_list", - params = { areas_selector = areas_selector, member = app.session.member } -} +execute.view { module = "unit", view = "_head", params = { unit = unit } } -tabs[#tabs+1] = { - name = "timeline", - label = _"Latest events", - module = "event", - view = "_list", - params = { for_unit = unit } -} -tabs[#tabs+1] = { - name = "open", - label = _"Open issues", - module = "issue", - view = "_list", - params = { - for_state = "open", - issues_selector = open_issues_selector, for_unit = true - } -} -tabs[#tabs+1] = { - name = "closed", - label = _"Closed issues", - module = "issue", - view = "_list", - params = { - for_state = "closed", - issues_selector = closed_issues_selector, for_unit = true +execute.view { + module = "unit", view = "_sidebar", params = { + unit = unit } } +execute.view { + module = "unit", view = "_sidebar_whatcanido", params = { + unit = unit + } +} + +execute.view { + module = "unit", view = "_sidebar_members", params = { + unit = unit + } +} + +execute.view { + module = "issue", + view = "_list2", + params = { for_unit = unit, head = function () + ui.heading { attr = { class = "left" }, level = 1, content = unit.name } + end } +} + +--[[ if app.session:has_access("all_pseudonymous") then tabs[#tabs+1] = { name = "eligible_voters", @@ -104,4 +88,6 @@ } end -ui.tabs(tabs) \ No newline at end of file +ui.tabs(tabs) + +--]] \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/vote/_action/update.lua --- a/app/main/vote/_action/update.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/vote/_action/update.lua Thu Jul 10 01:19:48 2014 +0200 @@ -3,19 +3,23 @@ local issue = Issue:new_selector():add_where{ "id = ?", param.get("issue_id", atom.integer) }:for_share():single_object_mode():exec() -local preview = param.get("preview") and true or false +local preview = (param.get("preview") or param.get("edit")) and true or false if not app.session.member:has_voting_right_for_unit_id(issue.area.unit_id) then error("access denied") end -local update_comment = param.get("update_comment") == "1" and true or false +local update_comment = param.get("update_comment") and true or false if issue.state ~= "voting" and not issue.closed then slot.put_into("error", _"Voting has not started yet.") return false end +if (issue.phase_finished or issue.closed) and preview then + return +end + if issue.phase_finished or issue.closed and not update_comment then slot.put_into("error", _"This issue is already closed.") return false @@ -66,7 +70,22 @@ end end - local formatting_engine = param.get("formatting_engine") + local formatting_engine + if config.enforce_formatting_engine then + formatting_engine = config.enforce_formatting_engine + else + formatting_engine = param.get("formatting_engine") + local formatting_engine_valid = false + for i, fe in ipairs(config.formatting_engines) do + if formatting_engine == fe.id then + formatting_engine_valid = true + end + end + if not formatting_engine_valid then + error("invalid formatting engine!") + end + end + local comment = param.get("comment") if comment ~= direct_voter.comment then diff -r a6c7bf07badb -r 701a5cf6b067 app/main/vote/list.lua --- a/app/main/vote/list.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/vote/list.lua Thu Jul 10 01:19:48 2014 +0200 @@ -21,69 +21,29 @@ readonly = true end +if preview then + readonly = true +end + local submit_button_text = _"Finish voting" +local edit_button_text = _"Edit again" if issue.closed then - submit_button_text = _"Update voting comment" + submit_button_text = _"Save voting comment" + edit_button_text = _"Edit voting comment" end +execute.view { + module = "issue", view = "_head", params = { issue = issue } +} + local direct_voter if member then direct_voter = DirectVoter:by_pk(issue.id, member.id) - local str = _("Ballot of '#{member_name}' for issue ##{issue_id}", - {member_name = string.format('%s', - encode.url{ - module = "member", - view = "show", - id = member.id, - }, - encode.html(member.name)), - issue_id = string.format('%s', - encode.url{ - module = "issue", - view = "show", - id = issue.id, - }, - encode.html(tostring(issue.id))) - } - ) - ui.raw_title(str) else member = app.session.member - direct_voter = DirectVoter:by_pk(issue.id, member.id) - - ui.title(_"Voting") - - ui.actions(function() - ui.link{ - text = _"Cancel", - module = "issue", - view = "show", - id = issue.id - } - if direct_voter then - slot.put(" · ") - ui.link{ - text = _"Discard voting", - module = "vote", - action = "update", - params = { - issue_id = issue.id, - discard = true - }, - routing = { - default = { - mode = "redirect", - module = "issue", - view = "show", - id = issue.id - } - } - } - end - end) end @@ -144,10 +104,7 @@ end end - - if not readonly then - util.help("vote.list", _"Voting") slot.put('') slot.put('') end @@ -179,321 +136,436 @@ end } -ui.form{ - record = direct_voter, - attr = { - id = "voting_form", - class = readonly and "voting_form_readonly" or "voting_form_active" - }, - module = "vote", - action = "update", - params = { issue_id = issue.id }, - content = function() - if not readonly or preview then - local scoring = param.get("scoring") - if not scoring then - for i, initiative in ipairs(initiatives) do - local vote = initiative.vote - if vote then - tempvotings[initiative.id] = vote.grade - else - tempvotings[initiative.id] = 0 - end - end - local tempvotings_list = {} - for key, val in pairs(tempvotings) do - tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val) - end - if #tempvotings_list > 0 then - scoring = table.concat(tempvotings_list, ";") - else - scoring = "" - end - end - slot.put('') - -- TODO abstrahieren - ui.tag{ - tag = "input", - attr = { - type = "submit", - class = "voting_done1", - value = submit_button_text - } +if issue.state == "finished_with_winner" + or issue.state == "finished_without_winner" +then + + local members_selector = Member:new_selector() + :join("delegating_voter", nil, "delegating_voter.member_id = member.id") + :add_where{ "delegating_voter.issue_id = ?", issue.id } + :add_where{ "delegating_voter.delegate_member_ids[1] = ?", member.id } + :add_field("delegating_voter.weight", "voter_weight") + :join("issue", nil, "issue.id = delegating_voter.issue_id") + + ui.sidebar( "tab-members", function() + ui.sidebarHead(function() + ui.heading{ level = 2, content = _"Incoming delegations" } + end) + execute.view{ + module = "member", + view = "_list", + params = { + members_selector = members_selector, + trustee = member, + issue = issue, + initiative = initiative, + for_votes = true, no_filter = true, + member_class = "sidebarRow sidebarRowNarrow", } + } + end) +end + + +ui.section( function() + + ui.sectionHead( function() + if preview then + ui.heading { level = 1, content = _"Preview of voting ballot" } + elseif readonly then + local str = _("Ballot of '#{member_name}'", + {member_name = string.format('%s', + encode.url{ + module = "member", + view = "show", + id = member.id, + }, + encode.html(member.name)) + } + ) + ui.heading { level = 1, content = function () slot.put ( str ) end } + else + ui.heading { level = 1, content = _"Voting" } end - ui.container{ - attr = { id = "voting" }, + end ) + + ui.sectionRow( function() + + ui.form{ + record = direct_voter, + attr = { + id = "voting_form", + class = readonly and "voting_form_readonly" or "voting_form_active" + }, + module = "vote", + action = "update", + params = { issue_id = issue.id }, content = function() - local approval_index, disapproval_index = 0, 0 - for grade = max_grade, min_grade, -1 do - local entries = sections[grade] - local class - if grade > 0 then - class = "approval" - elseif grade < 0 then - class = "disapproval" - else - class = "abstention" + if not readonly or preview then + local scoring = param.get("scoring") + if not scoring then + for i, initiative in ipairs(initiatives) do + local vote = initiative.vote + if vote then + tempvotings[initiative.id] = vote.grade + else + tempvotings[initiative.id] = 0 + end + end + local tempvotings_list = {} + for key, val in pairs(tempvotings) do + tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val) + end + if #tempvotings_list > 0 then + scoring = table.concat(tempvotings_list, ";") + else + scoring = "" + end end - if - #entries > 0 or - (grade == 1 and not approval_used) or - (grade == -1 and not disapproval_used) or - grade == 0 - then - ui.container{ - attr = { class = class }, - content = function() - local heading - if class == "approval" then - approval_used = true - approval_index = approval_index + 1 - if approval_count > 1 then - if approval_index == 1 then - if #entries == 1 then - heading = _"Approval (first preference) [single entry]" + slot.put('') + end + if preview then + ui.heading{ level = 2, content = _"Your choice" } + elseif not readonly then + ui.heading{ level = 2, content = _"Make your choice by placing the initiatives" } + end + + ui.container{ + attr = { id = "voting" }, + content = function() + local approval_index, disapproval_index = 0, 0 + for grade = max_grade, min_grade, -1 do + local entries = sections[grade] + local class + if grade > 0 then + class = "approval" + elseif grade < 0 then + class = "disapproval" + else + class = "abstention" + end + if + #entries > 0 or + (grade == 1 and not approval_used) or + (grade == -1 and not disapproval_used) or + grade == 0 + then + ui.container{ + attr = { class = class }, + content = function() + local heading + if class == "approval" then + approval_used = true + approval_index = approval_index + 1 + if approval_count > 1 then + if approval_index == 1 then + if #entries == 1 then + heading = _"Approval (first preference) [single entry]" + else + heading = _"Approval (first preference) [many entries]" + end + elseif approval_index == 2 then + if #entries == 1 then + heading = _"Approval (second preference) [single entry]" + else + heading = _"Approval (second preference) [many entries]" + end + elseif approval_index == 3 then + if #entries == 1 then + heading = _"Approval (third preference) [single entry]" + else + heading = _"Approval (third preference) [many entries]" + end + else + if #entries == 1 then + heading = _"Approval (#th preference) [single entry]" + else + heading = _"Approval (#th preference) [many entries]" + end + end else - heading = _"Approval (first preference) [many entries]" - end - elseif approval_index == 2 then - if #entries == 1 then - heading = _"Approval (second preference) [single entry]" - else - heading = _"Approval (second preference) [many entries]" + if #entries == 1 then + heading = _"Approval [single entry]" + else + heading = _"Approval [many entries]" + end end - elseif approval_index == 3 then - if #entries == 1 then - heading = _"Approval (third preference) [single entry]" + elseif class == "abstention" then + if #entries == 1 then + heading = _"Abstention [single entry]" + else + heading = _"Abstention [many entries]" + end + elseif class == "disapproval" then + disapproval_used = true + disapproval_index = disapproval_index + 1 + if disapproval_count > disapproval_index + 1 then + if #entries == 1 then + heading = _"Disapproval (prefer to lower blocks) [single entry]" + else + heading = _"Disapproval (prefer to lower blocks) [many entries]" + end + elseif disapproval_count == 2 and disapproval_index == 1 then + if #entries == 1 then + heading = _"Disapproval (prefer to lower block) [single entry]" + else + heading = _"Disapproval (prefer to lower block) [many entries]" + end + elseif disapproval_index == disapproval_count - 1 then + if #entries == 1 then + heading = _"Disapproval (prefer to last block) [single entry]" + else + heading = _"Disapproval (prefer to last block) [many entries]" + end else - heading = _"Approval (third preference) [many entries]" - end - else - if #entries == 1 then - heading = _"Approval (#th preference) [single entry]" - else - heading = _"Approval (#th preference) [many entries]" + if #entries == 1 then + heading = _"Disapproval [single entry]" + else + heading = _"Disapproval [many entries]" + end end end - else - if #entries == 1 then - heading = _"Approval [single entry]" - else - heading = _"Approval [many entries]" - end - end - elseif class == "abstention" then - if #entries == 1 then - heading = _"Abstention [single entry]" - else - heading = _"Abstention [many entries]" - end - elseif class == "disapproval" then - disapproval_used = true - disapproval_index = disapproval_index + 1 - if disapproval_count > disapproval_index + 1 then - if #entries == 1 then - heading = _"Disapproval (prefer to lower blocks) [single entry]" - else - heading = _"Disapproval (prefer to lower blocks) [many entries]" - end - elseif disapproval_count == 2 and disapproval_index == 1 then - if #entries == 1 then - heading = _"Disapproval (prefer to lower block) [single entry]" - else - heading = _"Disapproval (prefer to lower block) [many entries]" - end - elseif disapproval_index == disapproval_count - 1 then - if #entries == 1 then - heading = _"Disapproval (prefer to last block) [single entry]" - else - heading = _"Disapproval (prefer to last block) [many entries]" - end - else - if #entries == 1 then - heading = _"Disapproval [single entry]" - else - heading = _"Disapproval [many entries]" - end - end - end - ui.tag { - tag = "div", - attr = { class = "cathead" }, - content = heading - } - for i, initiative in ipairs(entries) do - ui.container{ - attr = { - class = "movable", - id = "entry_" .. tostring(initiative.id) - }, - content = function() - local initiators_selector = initiative:get_reference_selector("initiating_members") - :add_where("accepted") - local initiators = initiators_selector:exec() - local initiator_names = {} - for i, initiator in ipairs(initiators) do - initiator_names[#initiator_names+1] = initiator.name - end - local initiator_names_string = table.concat(initiator_names, ", ") + ui.tag { + tag = "div", + attr = { class = "cathead" }, + content = heading + } + for i, initiative in ipairs(entries) do ui.container{ - attr = { style = "float: right; position: relative;" }, + attr = { + class = "movable", + id = "entry_" .. tostring(initiative.id) + }, content = function() - ui.link{ - attr = { class = "clickable" }, - content = _"Show", - module = "initiative", - view = "show", - id = initiative.id - } - slot.put(" ") - ui.link{ - attr = { class = "clickable", target = "_blank" }, - content = _"(new window)", - module = "initiative", - view = "show", - id = initiative.id + local initiators_selector = initiative:get_reference_selector("initiating_members") + :add_where("accepted") + local initiators = initiators_selector:exec() + local initiator_names = {} + for i, initiator in ipairs(initiators) do + initiator_names[#initiator_names+1] = initiator.name + end + local initiator_names_string = table.concat(initiator_names, ", ") + ui.container{ + attr = { style = "float: right; position: relative;" }, + content = function() + ui.link{ + attr = { class = "clickable" }, + content = _"Show", + module = "initiative", + view = "show", + id = initiative.id + } + slot.put(" ") + ui.link{ + attr = { class = "clickable", target = "_blank" }, + content = _"(new window)", + module = "initiative", + view = "show", + id = initiative.id + } + if not readonly then + slot.put(" ") + ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" } + end + end } if not readonly then - slot.put(" ") - ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" } - end - end - } - if not readonly then - ui.container{ - attr = { style = "float: left; position: relative;" }, - content = function() - ui.tag{ - tag = "input", - attr = { - onclick = "if (jsFail) return true; voting_moveUp(this.parentNode.parentNode); return(false);", - name = "move_up_" .. tostring(initiative.id), - class = not disabled and "clickable" or nil, - type = "image", - src = encode.url{ static = "icons/move_up.png" }, - alt = _"Move up" - } - } - slot.put(" ") - ui.tag{ - tag = "input", - attr = { - onclick = "if (jsFail) return true; voting_moveDown(this.parentNode.parentNode); return(false);", - name = "move_down_" .. tostring(initiative.id), - class = not disabled and "clickable" or nil, - type = "image", - src = encode.url{ static = "icons/move_down.png" }, - alt = _"Move down" - } - } - slot.put(" ") - end - } - end - ui.container{ - content = function() - ui.tag{ content = "i" .. initiative.id .. ": " } - ui.tag{ content = initiative.shortened_name } - slot.put("
") - for i, initiator in ipairs(initiators) do - ui.link{ - attr = { class = "clickable" }, - content = function () - execute.view{ - module = "member_image", - view = "_show", - params = { - member = initiator, - image_type = "avatar", - show_dummy = true, - class = "micro_avatar", - popup_text = text + ui.container{ + attr = { style = "float: left; position: relative;" }, + content = function() + ui.tag{ + tag = "input", + attr = { + onclick = "if (jsFail) return true; voting_moveUp(this.parentNode.parentNode); return(false);", + name = "move_up_" .. tostring(initiative.id), + class = not disabled and "clickable" or nil, + type = "image", + src = encode.url{ static = "icons/move_up.png" }, + alt = _"Move up" + } + } + slot.put(" ") + ui.tag{ + tag = "input", + attr = { + onclick = "if (jsFail) return true; voting_moveDown(this.parentNode.parentNode); return(false);", + name = "move_down_" .. tostring(initiative.id), + class = not disabled and "clickable" or nil, + type = "image", + src = encode.url{ static = "icons/move_down.png" }, + alt = _"Move down" } } - end, - module = "member", view = "show", id = initiator.id + slot.put(" ") + end } - slot.put(" ") - ui.tag{ content = initiator.name } - slot.put(" ") end + ui.container{ + content = function() + ui.tag{ content = "i" .. initiative.id .. ": " } + ui.tag{ content = initiative.shortened_name } + slot.put("
") + for i, initiator in ipairs(initiators) do + ui.link{ + attr = { class = "clickable" }, + content = function () + execute.view{ + module = "member_image", + view = "_show", + params = { + member = initiator, + image_type = "avatar", + show_dummy = true, + class = "micro_avatar", + popup_text = text + } + } + end, + module = "member", view = "show", id = initiator.id + } + slot.put(" ") + ui.tag{ content = initiator.name } + slot.put(" ") + end + end + } end } end + end + } + end + end + end + } + if app.session.member_id and preview then + local formatting_engine = param.get("formatting_engine") or config.enforce_formatting_engine + local comment = param.get("comment") + if comment and #comment > 0 then + local rendered_comment = format.wiki_text(comment, formatting_engine) + ui.heading{ level = "2", content = _"Voting comment" } + ui.container { attr = { class = "member_statement" }, content = function() + slot.put(rendered_comment) + end } + slot.put("
") + end + end + if (readonly or direct_voter and direct_voter.comment) and not preview and not (app.session.member_id == member.id) then + local text + if direct_voter and direct_voter.comment_changed then + text = _("Voting comment (last updated: #{timestamp})", { timestamp = format.timestamp(direct_voter.comment_changed) }) + elseif direct_voter and direct_voter.comment then + text = _"Voting comment" + end + if text then + ui.heading{ level = "2", content = text } + end + if direct_voter and direct_voter.comment then + local rendered_comment = direct_voter:get_content('html') + ui.container { attr = { class = "member_statement" }, content = function() + slot.put(rendered_comment) + end } + slot.put("
") + end + end + if app.session.member_id and app.session.member_id == member.id then + if (not readonly or direct_voter) and not preview then + ui.container{ content = function() + if not config.enforce_formatting_engine then + ui.field.select{ + label = _"Wiki engine for statement", + name = "formatting_engine", + foreign_records = config.formatting_engines, + attr = {id = "formatting_engine"}, + foreign_id = "id", + foreign_name = "name", + value = param.get("formatting_engine") or direct_voter and direct_voter.formatting_engine + } + end + ui.heading { level = 2, content = _"Voting comment (optional)" } + ui.field.text{ + name = "comment", + multiline = true, + value = param.get("comment") or direct_voter and direct_voter.comment, + attr = { style = "height: 10ex; width: 100%;" }, + } + end } + end + + if preview then + if not config.enforce_formatting_engine then + ui.field.hidden{ name = "formatting_engine", value = param.get("formatting_engine") } + end + ui.field.hidden{ name = "comment", value = param.get("comment") or direct_voter and direct_voter.comment } + end + + if not readonly or direct_voter or preview then + ui.container{ content = function() + if preview then + slot.put(" ") + ui.tag{ + tag = "input", + attr = { + type = "submit", + class = "btn btn-default", + name = issue.closed and "update_comment" or nil, + value = submit_button_text -- finish voting / update comment } - end + } end - } + if not preview then + ui.tag{ + tag = "input", + attr = { + type = "submit", + name = "preview", + class = "btn btn-default", + value = _"Preview", + } + } + else + slot.put(" ") + ui.tag{ + tag = "input", + attr = { + type = "submit", + name = "edit", + class = "btn-link", + value = edit_button_text, + } + } + end + end } end end end } - if app.session.member_id and preview then - local formatting_engine = param.get("formatting_engine") - local comment = param.get("comment") - local rendered_comment = format.wiki_text(comment, formatting_engine) - slot.put(rendered_comment) - end - if (readonly or direct_voter and direct_voter.comment) and not preview then - local text - if direct_voter and direct_voter.comment_changed then - text = _("Voting comment (last updated: #{timestamp})", { timestamp = format.timestamp(direct_voter.comment_changed) }) - elseif direct_voter and direct_voter.comment then - text = _"Voting comment" - end - if text then - ui.heading{ level = "2", content = text } - end - if direct_voter and direct_voter.comment then - local rendered_comment = direct_voter:get_content('html') - ui.container{ attr = { class = "member_statement" }, content = function() - slot.put(rendered_comment) - end } - slot.put("
") - end + slot.put("
") + ui.link{ + text = _"Cancel", + module = "issue", + view = "show", + id = issue.id + } + if direct_voter then + slot.put(" | ") + ui.link { + module = "vote", action = "update", + params = { + issue_id = issue.id, + discard = true + }, + routing = { + default = { + mode = "redirect", + module = "issue", + view = "show", + id = issue.id + } + }, + text = _"Discard my vote" + } end - if app.session.member_id and app.session.member_id == member.id then - if not readonly or direct_voter then - ui.field.hidden{ name = "update_comment", value = param.get("update_comment") or issue.closed and "1" } - ui.field.select{ - label = _"Wiki engine for statement", - name = "formatting_engine", - foreign_records = { - { id = "rocketwiki", name = "RocketWiki" }, - { id = "compat", name = _"Traditional wiki syntax" } - }, - attr = {id = "formatting_engine"}, - foreign_id = "id", - foreign_name = "name", - value = param.get("formatting_engine") or direct_voter and direct_voter.formatting_engine - } - ui.field.text{ - label = _"Voting comment (optional)", - name = "comment", - multiline = true, - value = param.get("comment") or direct_voter and direct_voter.comment, - attr = { style = "height: 20ex;" }, - } - ui.submit{ - name = "preview", - value = _"Preview voting comment", - attr = { class = "preview" } - } - end - if not readonly or preview or direct_voter then - slot.put(" ") - ui.tag{ - tag = "input", - attr = { - type = "submit", - class = "voting_done2", - value = submit_button_text - } - } - end - end - end -} - + end ) +end ) \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 app/main/vote/show_incoming.lua --- a/app/main/vote/show_incoming.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/app/main/vote/show_incoming.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,5 +1,20 @@ -local initiative = Initiative:by_id(param.get("initiative_id", atom.integer)) -local issue = initiative.issue +local initiative = Initiative:by_id(param.get("initiative_id")) + +local issue + +if initiative then + issue = initiative.issue +else + issue = Issue:by_id(param.get("issue_id")) +end + +if app.session.member_id then + if initiative then + initiative:load_everything_for_member_id(app.session.member.id) + end + issue:load_everything_for_member_id(app.session.member.id) +end + local member = Member:by_id(param.get("member_id", atom.integer)) local members_selector = Member:new_selector() @@ -9,13 +24,55 @@ :add_field("delegating_voter.weight", "voter_weight") :join("issue", nil, "issue.id = delegating_voter.issue_id") + execute.view{ - module = "member", - view = "_list", - params = { - members_selector = members_selector, - initiative = initiative, - trustee = member, - for_votes = true + module = "issue", view = "_head", params = { + issue = issue, initiative = initiative + } +} + +execute.view{ module = "issue", view = "_sidebar_state", params = { + issue = issue, +} } + +execute.view { + module = "issue", view = "_sidebar_issue", params = { + issue = issue, + highlight_initiative_id = initiative and initiative.id or nil, + } +} + +execute.view { + module = "issue", view = "_sidebar_whatcanido", params = { + issue = issue } -} \ No newline at end of file +} + +execute.view { + module = "issue", view = "_sidebar_members", params = { + issue = issue, + initiative = initiative + } +} + + +ui.section( function() + + ui.sectionHead( function() + ui.heading{ level = 1, content = _("Incoming delegations for '#{member}'", { member = member.name }) } + end) + + execute.view{ + module = "member", + view = "_list", + params = { + members_selector = members_selector, + trustee = member, + issue = issue, + initiative = initiative, + for_votes = true, no_filter = true, + + } + } + +end ) diff -r a6c7bf07badb -r 701a5cf6b067 config/devel.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/devel.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,288 @@ +-- ======================================================================== +-- MANDATORY (MUST BE CAREFULLY CHECKED AND PROPERLY SET!) +-- ======================================================================== + +-- Name of this instance, defaults to name of config file +-- ------------------------------------------------------------------------ +config.instance_name = "Public Software Group e.V." + + +-- Information about service provider (HTML) +-- ------------------------------------------------------------------------ +config.app_service_provider = "Snake Oil
10000 Berlin
Germany" + + +-- A HTML formatted text the user has to accept while registering +-- ------------------------------------------------------------------------ +config.use_terms = "

Terms of Use

Insert terms here

" + + +-- Checkbox(es) the user has to accept while registering +-- ------------------------------------------------------------------------ +config.use_terms_checkboxes = { + { + name = "terms_of_use_v1", + html = "I accept the terms of use.", + not_accepted_error = "You have to accept the terms of use to be able to register." + }, +-- { +-- name = "extra_terms_of_use_v1", +-- html = "I accept the extra terms of use.", +-- not_accepted_error = "You have to accept the extra terms of use to be able to register." +-- } +} + + +-- Absolute base url of application +-- ------------------------------------------------------------------------ +config.absolute_base_url = "http://192.168.1.34/lf3/" + + +-- Connection information for the LiquidFeedback database +-- ------------------------------------------------------------------------ +config.database = { engine='postgresql', dbname='liquid_feedback' } +config.database = { engine='postgresql', dbname='lftest' } + + +-- Location of the rocketwiki binaries +-- ------------------------------------------------------------------------ +config.enforce_formatting_engine = "markdown2" + +config.formatting_engines = { + { id = "markdown2", + name = "python-markdown2", + executable = "markdown2", + args = {'-s', 'escape', '-x', 'cuddled-lists,nofollow,wiki-tables'}, + remove_images = true + }, + { id = "markdown_py", + name = "Python Markdown", + executable = "markdown_py", + args = {'-s', 'escape', '-x', 'extra', '-x', 'nl2br', '-x', 'sane_lists'}, + remove_images = true + }, + { id = "rocketwiki", + name = "RocketWiki", + executable = "/opt/rocketwiki-lqfb/rocketwiki-lqfb", + remove_images = false + }, + { id = "compat", + name = "Traditional WIKI syntax", + executable = "/opt/rocketwiki-lqfb/rocketwiki-lqfb-compat", + remove_images = false + } +} + +-- Public access level +-- ------------------------------------------------------------------------ +-- Available options: +-- "none" +-- -> Closed user group, no public access at all +-- (except login/registration/password reset) +-- "anonymous" +-- -> Shows only initiative/suggestions texts and aggregated +-- supporter/voter counts +-- "authors_pseudonymous" +-- -> Like anonymous, but shows screen names of authors +-- "all_pseudonymous" +-- -> Show everything a member can see, except profile pages +-- "everything" +-- -> Show everything a member can see, including profile pages +-- ------------------------------------------------------------------------ +config.public_access = "all_pseudonymous" + + + +-- ======================================================================== +-- OPTIONAL +-- Remove leading -- to use a option +-- ======================================================================== + +-- List of enabled languages, defaults to available languages +-- ------------------------------------------------------------------------ +-- config.enabled_languages = { 'en', 'de', 'eo', 'el', 'hu', 'it', 'nl', 'zh-TW' } + +-- Default language, defaults to "en" +-- ------------------------------------------------------------------------ +-- config.default_lang = "de" + +-- after how long is a user considered inactive and the trustee will see warning, +-- notation is according to postgresql intervals, default: no warning at all +-- ------------------------------------------------------------------------ +config.delegation_warning_time = '1 hour' + +-- after which time a user is suggested to (_soft) or forced to (_hard) +-- confirm unit and area delegations. default: no confirmation at all +-- ------------------------------------------------------------------------ +-- config.check_delegations_interval_hard = "1 day" +-- config.check_delegations_interval_soft = "3 seconds" + +-- default options should be checked when confirming delegations +-- options: "confirm", "revoke" and "none" +-- ------------------------------------------------------------------------ +-- config.check_delegations_default = "confirm" + +-- Prefix of all automatic mails, defaults to "[Liquid Feedback] " +-- ------------------------------------------------------------------------ +-- config.mail_subject_prefix = "[LiquidFeedback] " + +-- Sender of all automatic mails, defaults to system defaults +-- ------------------------------------------------------------------------ +-- config.mail_envelope_from = "liquidfeedback@example.com" +-- config.mail_from = { name = "LiquidFeedback", address = "liquidfeedback@example.com" } +-- config.mail_reply_to = { name = "Support", address = "support@example.com" } + +-- Configuration of password hashing algorithm (defaults to "crypt_sha512") +-- ------------------------------------------------------------------------ +-- config.password_hash_algorithm = "crypt_sha512" +-- config.password_hash_algorithm = "crypt_sha256" +-- config.password_hash_algorithm = "crypt_md5" + +-- Number of rounds for crypt_sha* algorithms, minimum and maximum +-- (defaults to minimum 10000 and maximum 20000) +-- ------------------------------------------------------------------------ +-- config.password_hash_min_rounds = 10000 +-- config.password_hash_max_rounds = 20000 + +-- Supply custom url for avatar/photo delivery +-- ------------------------------------------------------------------------ +-- config.fastpath_url_func = nil + +-- Local directory for database dumps offered for download +-- ------------------------------------------------------------------------ +-- config.download_dir = nil + +-- Special use terms for database dump download +-- ------------------------------------------------------------------------ +-- config.download_use_terms = "=== Download use terms ===\n" + +-- Use custom image conversion, defaults to ImageMagick's convert +-- ------------------------------------------------------------------------ +--config.member_image_content_type = "image/jpeg" +--config.member_image_convert_func = { +-- avatar = function(data) return extos.pfilter(data, "convert", "jpeg:-", "-thumbnail", "48x48", "jpeg:-") end, +-- photo = function(data) return extos.pfilter(data, "convert", "jpeg:-", "-thumbnail", "240x240", "jpeg:-") end +--} + +config.member_image_content_type = "image/jpeg" +config.member_image_convert_func = { + avatar = function(data) return extos.pfilter(data, "convert", + "jpeg:-", + "-set", "option:distort:viewport", + "%[fx:min(w,h)]x%[fx:min(w,h)]+%[fx:max((w-h)/2,0)]+%[fx:max((h-w)/2,0)]", + "-filter", "point", + "-distort", "SRT", "0", + "+repage", + "-define", "filter:filter=Sinc", + "-define", "filter:window=Jinc", + "-define", "filter:lobes=3", + "-thumbnail", "48x48", + "jpeg:-" + ) end, + photo = function(data) return extos.pfilter(data, "convert", + "jpeg:-", + "-define", "filter:filter=Sinc", + "-define", "filter:window=Jinc", + "-define", "filter:lobes=3", + "-thumbnail", "240x240", + "jpeg:-" + ) end +} + + +-- Display a html formatted public message of the day +-- ------------------------------------------------------------------------ +-- config.motd_public = "

Message of the day (public)

The MOTD is formatted with HTML

" + +-- Display a html formatted internal message of the day +-- ------------------------------------------------------------------------ +-- config.motd_intern = "

Message of the day (intern)

The MOTD is formatted with HTML

" + +-- Automatic issue related discussion URL +-- ------------------------------------------------------------------------ +-- config.issue_discussion_url_func = function(issue) +-- return "http://example.com/discussion/issue_" .. tostring(issue.id) +-- end + +-- Configuration of "tell others" +-- ------------------------------------------------------------------------ +config.tell_others = { + initiative = function (initiative) + local text = "i" .. initiative.id .. ": " .. initiative.name .. " " .. request.get_absolute_baseurl() .. "initiative/" .. initiative.id .. ".html" + return { + { content = "tweet this initiative", external = "https://twitter.com/intent/tweet?text=" .. encode.url_part(text) }, + { content = "send link with e-mail", external = "mailto:?subject=" .. encode.url_part(initiative.display_name) .. "&body=" .. encode.url_part(text) } + } + end +} + +-- Integration of Etherpad, disabled by default +-- ------------------------------------------------------------------------ +--config.etherpad = { +-- base_url = "http://example.com:9001/", +-- api_base = "http://localhost:9001/", +-- api_key = "mysecretapikey", +-- group_id = "mygroupname", +-- cookie_path = "/" +--} + +-- Free timings, may be used together with polling policies +-- ------------------------------------------------------------------------ +-- This example expects a date string entered in the free timing field +-- by the user creating a poll, interpreting it as target date for then +-- poll and splits the remainig time at the ratio of 4:1:2 +-- Please note, polling policies never have an admission phase + + +config.free_timing = { + calculate_func = function(policy, timing_string) + function interval_by_seconds(secs) + local secs_per_day = 60 * 60 * 24 + local days + days = math.floor(secs / secs_per_day) + secs = secs - days * secs_per_day + return days .. " days " .. secs .. " seconds" + end + local target_date = parse.date(timing_string, atom.date) + if not target_date then + return false + end + local target_timestamp = target_date.midday + local now = atom.timestamp:get_current() + trace.debug(target_timestamp, now) + local duration = target_timestamp - now + if duration < 0 then + return false + end + return { + discussion = interval_by_seconds(duration / 7 * 4), + verification = interval_by_seconds(duration / 7 * 1), + voting = interval_by_seconds(duration / 7 * 2) + } + end, + available_func = function(policy) + return { + { name = "End of 2013", id = '2013-12-31' }, + { name = "End of 2014", id = '2014-12-31' }, + { name = "End of 2015", id = '2015-12-31' } + } + end +} + + +config.enable_debug_trace = true + +-- WebMCP accelerator +-- 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' +-- if cgi then collectgarbage("stop") end + + +-- ======================================================================== +-- Do main initialisation (DO NOT REMOVE FOLLOWING SECTION) +-- ======================================================================== + +execute.config("init") diff -r a6c7bf07badb -r 701a5cf6b067 config/example.lua --- a/config/example.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/config/example.lua Thu Jul 10 01:19:48 2014 +0200 @@ -12,9 +12,9 @@ config.app_service_provider = "Snake Oil
10000 Berlin
Germany" --- A rocketwiki formatted text the user has to accept while registering +-- A HTML formatted text the user has to accept while registering -- ------------------------------------------------------------------------ -config.use_terms = "=== Terms of Use ===" +config.use_terms = "

Terms of Use

Insert terms here

" -- Checkbox(es) the user has to accept while registering @@ -45,9 +45,29 @@ -- Location of the rocketwiki binaries -- ------------------------------------------------------------------------ -config.formatting_engine_executeables = { - rocketwiki= "/opt/rocketwiki-lqfb/rocketwiki-lqfb", - compat = "/opt/rocketwiki-lqfb/rocketwiki-lqfb-compat" +config.enforce_formatting_engine = "markdown2" +config.formatting_engines = { + { id = "markdown2", + name = "python-markdown2", + executable = "markdown2", + args = {'-s', 'escape', '-x', 'cuddled-lists,nofollow,wiki-tables'}, + remove_images = true + }, + { id = "markdown_py", + name = "Python Markdown", + executable = "markdown_py", + args = {'-s', 'escape', '-x', 'extra', '-x', 'nl2br', '-x', 'sane_lists'}, + remove_images = true + }, + { id = "rocketwiki", + name = "RocketWiki", + executable = "/opt/rocketwiki-lqfb/rocketwiki-lqfb" + }, + { id = "compat", + name = "Traditional WIKI syntax", + executable = "/opt/rocketwiki-lqfb/rocketwiki-lqfb-compat" + }, + } @@ -143,9 +163,13 @@ -- photo = function(data) return extos.pfilter(data, "convert", "jpeg:-", "-thumbnail", "240x240", "jpeg:-") end --} --- Display a public message of the day +-- Display a html formatted public message of the day -- ------------------------------------------------------------------------ --- config.motd_public = "===Message of the day===\nThe MOTD is formatted with rocket wiki" +-- config.motd_public = "

Message of the day (public)

The MOTD is formatted with HTML

" + +-- Display a html formatted internal message of the day +-- ------------------------------------------------------------------------ +-- config.motd_intern = "

Message of the day (intern)

The MOTD is formatted with HTML

" -- Automatic issue related discussion URL -- ------------------------------------------------------------------------ diff -r a6c7bf07badb -r 701a5cf6b067 config/init.lua --- a/config/init.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/config/init.lua Thu Jul 10 01:19:48 2014 +0200 @@ -3,7 +3,7 @@ -- (except when you really know what you are doing!) -- ======================================================================== -config.app_version = "2.2.6" +config.app_version = "3.0.0" if not config.password_hash_algorithm then config.password_hash_algorithm = "crypt_sha512" @@ -18,7 +18,7 @@ end if config.enabled_languages == nil then - config.enabled_languages = { 'en', 'de', 'eo', 'el', 'hu', 'it', 'nl', 'zh-Hans', 'zh-TW' } + config.enabled_languages = { 'en', 'de' } --, 'eo', 'el', 'hu', 'it', 'nl', 'zh-Hans', 'zh-TW' } end if config.default_lang == nil then diff -r a6c7bf07badb -r 701a5cf6b067 config/lf3.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/lf3.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,290 @@ +-- ======================================================================== +-- MANDATORY (MUST BE CAREFULLY CHECKED AND PROPERLY SET!) +-- ======================================================================== + +-- Name of this instance, defaults to name of config file +-- ------------------------------------------------------------------------ +config.instance_name = "Public Software Group e.V." + + +-- Information about service provider (HTML) +-- ------------------------------------------------------------------------ +config.app_service_provider = [[ +Public Software Group e. V.
+Johannisstr. 12
+10117 Berlin
+Germany

+eingetragen im Vereinsregister des Amtsgerichtes Charlottenburg unter der + Registernummer VR 28873 B
+vertreten durch die Vorstandsmitglieder Jan Behrens, Axel Kistner, Andreas + Nitsche und Björn Swierczek jeweils mit Einzelvertretungsbefugnis +]] + + +-- A HTML formatted text the user has to accept while registering +-- ------------------------------------------------------------------------ +config.use_terms = [[ +

Terms of Use

+

+ All data display below and all data you enter later while using the system + and all data you are submitting via the programming interface will be + stored in the LiquidFeedback database and published. Every access to the + system is subject of tracing and logging for development purposes. +

+

+ Please notice, this is a **public test dedicated to developers**: serious + errors can happen or private data unintentionally published. +

+

+ Everything is ON YOUR OWN RISK +

+]] + +-- Checkbox(es) the user has to accept while registering +-- ------------------------------------------------------------------------ +config.use_terms_checkboxes = { + { + name = "terms_of_use_20140514", + html = "I accept the terms of use.", + not_accepted_error = "You have to accept the terms of use to be able to register." + }, +-- { +-- name = "extra_terms_of_use_v1", +-- html = "I accept the extra terms of use.", +-- not_accepted_error = "You have to accept the extra terms of use to be able to register." +-- } +} + + +-- Absolute base url of application +-- ------------------------------------------------------------------------ +config.absolute_base_url = "http://dev.liquidfeedback.org/lf3/" + + +-- Connection information for the LiquidFeedback database +-- ------------------------------------------------------------------------ +config.database = { engine='postgresql', dbname='lf3' } + + +-- Location of the rocketwiki binaries +-- ------------------------------------------------------------------------ +config.enforce_formatting_engine = "markdown2" + +config.formatting_engines = { + { id = "markdown_py", + name = "Python Markdown", + executable = "markdown_py", + args = {'/dev/stdin', '-s', 'escape', '-x', 'extra', '-x', 'nl2br', '-x', 'sane_lists'}, + remove_images = true + }, + { id = "markdown2", + name = "markdown2", + executable = "markdown2", + args = {'-s', 'escape', '-x', 'cuddled-lists,nofollow,wiki-tables'}, + remove_images = true + }, + { id = "multimarkdown", + name = "MultiMarkdown", + executable = "multimarkdown", + args = {'--filter-html', '--filter-styles', '--nolabels' ,'-x'} + }, + { id = "rocketwiki", + name = "RocketWiki", + executable = "/opt/liquid_feedback3/rocketwiki-lqfb/rocketwiki-lqfb", + remove_images = false + }, + { id = "compat", + name = "Traditional WIKI syntax", + executable = "/opt/liquid_feedback3/rocketwiki-lqfb/rocketwiki-lqfb-compat", + remove_images = false + } +} + +-- Public access level +-- ------------------------------------------------------------------------ +-- Available options: +-- "none" +-- -> Closed user group, no public access at all +-- (except login/registration/password reset) +-- "anonymous" +-- -> Shows only initiative/suggestions texts and aggregated +-- supporter/voter counts +-- "authors_pseudonymous" +-- -> Like anonymous, but shows screen names of authors +-- "all_pseudonymous" +-- -> Show everything a member can see, except profile pages +-- "everything" +-- -> Show everything a member can see, including profile pages +-- ------------------------------------------------------------------------ +config.public_access = "none" + + + +-- ======================================================================== +-- OPTIONAL +-- Remove leading -- to use a option +-- ======================================================================== + +-- List of enabled languages, defaults to available languages +-- ------------------------------------------------------------------------ +-- config.enabled_languages = { 'en', 'de', 'eo', 'el', 'hu', 'it', 'nl', 'zh-TW' } +config.enabled_languages = { 'en', 'de' } + +-- Default language, defaults to "en" +-- ------------------------------------------------------------------------ +-- config.default_lang = "de" + +-- after how long is a user considered inactive and the trustee will see warning, +-- notation is according to postgresql intervals, default: no warning at all +-- ------------------------------------------------------------------------ +config.delegation_warning_time = '3 month' + +-- after which time a user is suggested to (_soft) or forced to (_hard) +-- confirm unit and area delegations. default: no confirmation at all +-- ------------------------------------------------------------------------ +-- config.check_delegations_interval_hard = "1 day" +-- config.check_delegations_interval_soft = "3 seconds" + +-- default options should be checked when confirming delegations +-- options: "confirm", "revoke" and "none" +-- ------------------------------------------------------------------------ +-- config.check_delegations_default = "confirm" + +-- Prefix of all automatic mails, defaults to "[Liquid Feedback] " +-- ------------------------------------------------------------------------ +config.mail_subject_prefix = "[LiquidFeedback 3.0 Test] " + +-- Sender of all automatic mails, defaults to system defaults +-- ------------------------------------------------------------------------ +config.mail_envelope_from = "lqfb-maintainers@public-software-group.org" +config.mail_from = { name = "LiquidFeedback", address = "lqfb-maintainers@public-software-group.org" } +--config.mail_reply_to = { name = "Support", address = "support@example.com" } + +-- Configuration of password hashing algorithm (defaults to "crypt_sha512") +-- ------------------------------------------------------------------------ +-- config.password_hash_algorithm = "crypt_sha512" +-- config.password_hash_algorithm = "crypt_sha256" +-- config.password_hash_algorithm = "crypt_md5" + +-- Number of rounds for crypt_sha* algorithms, minimum and maximum +-- (defaults to minimum 10000 and maximum 20000) +-- ------------------------------------------------------------------------ +-- config.password_hash_min_rounds = 10000 +-- config.password_hash_max_rounds = 20000 + +-- Supply custom url for avatar/photo delivery +-- ------------------------------------------------------------------------ +-- config.fastpath_url_func = nil + +-- Local directory for database dumps offered for download +-- ------------------------------------------------------------------------ +-- config.download_dir = nil + +-- Special use terms for database dump download +-- ------------------------------------------------------------------------ +-- config.download_use_terms = "=== Download use terms ===\n" + +-- Use custom image conversion, defaults to ImageMagick's convert +-- ------------------------------------------------------------------------ +--config.member_image_content_type = "image/jpeg" +--config.member_image_convert_func = { +-- avatar = function(data) return extos.pfilter(data, "convert", "jpeg:-", "-thumbnail", "48x48", "jpeg:-") end, +-- photo = function(data) return extos.pfilter(data, "convert", "jpeg:-", "-thumbnail", "240x240", "jpeg:-") end +--} + +-- Display a html formatted public message of the day +-- ------------------------------------------------------------------------ +-- config.motd_public = "

Message of the day (public)

The MOTD is formatted with HTML

" + +-- Display a html formatted internal message of the day +-- ------------------------------------------------------------------------ +-- config.motd_public = "

Message of the day (intern)

The MOTD is formatted with HTML

" + +-- Automatic issue related discussion URL +-- ------------------------------------------------------------------------ +-- config.issue_discussion_url_func = function(issue) +-- return "http://example.com/discussion/issue_" .. tostring(issue.id) +-- end + +-- Configuration of "tell others" +-- ------------------------------------------------------------------------ +config.tell_others = { + initiative = function (initiative) + local text = "i" .. initiative.id .. ": " .. initiative.name .. " " .. request.get_absolute_baseurl() .. "initiative/" .. initiative.id .. ".html" + return { + { content = "Tweet this initiative", external = "https://twitter.com/intent/tweet?text=" .. encode.url_part(text) }, + { content = "Send an eMail", external = "mailto:?subject=" .. encode.url_part(initiative.display_name) .. "&body=" .. encode.url_part(text) } + } + end +} + +-- Integration of Etherpad, disabled by default +-- ------------------------------------------------------------------------ +--config.etherpad = { +-- base_url = "http://example.com:9001/", +-- api_base = "http://localhost:9001/", +-- api_key = "mysecretapikey", +-- group_id = "mygroupname", +-- cookie_path = "/" +--} + +-- Free timings, may be used together with polling policies +-- ------------------------------------------------------------------------ +-- This example expects a date string entered in the free timing field +-- by the user creating a poll, interpreting it as target date for then +-- poll and splits the remainig time at the ratio of 4:1:2 +-- Please note, polling policies never have an admission phase + + +config.free_timing = { + calculate_func = function(policy, timing_string) + function interval_by_seconds(secs) + local secs_per_day = 60 * 60 * 24 + local days + days = math.floor(secs / secs_per_day) + secs = secs - days * secs_per_day + return days .. " days " .. secs .. " seconds" + end + local target_date = parse.date(timing_string, atom.date) + if not target_date then + return false + end + local target_timestamp = target_date.midday + local now = atom.timestamp:get_current() + trace.debug(target_timestamp, now) + local duration = target_timestamp - now + if duration < 0 then + return false + end + return { + discussion = interval_by_seconds(duration / 7 * 4), + verification = interval_by_seconds(duration / 7 * 1), + voting = interval_by_seconds(duration / 7 * 2) + } + end, + available_func = function(policy) + return { + { name = "End of 2014", id = '2014-12-31' }, + { name = "End of 2015", id = '2015-12-31' }, + { name = "End of 2016", id = '2016-12-31' } + } + end +} + + +config.enable_debug_trace = true + +-- WebMCP accelerator +-- 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' +-- if cgi then collectgarbage("stop") end + + +-- ======================================================================== +-- Do main initialisation (DO NOT REMOVE FOLLOWING SECTION) +-- ======================================================================== + +execute.config("init") diff -r a6c7bf07badb -r 701a5cf6b067 env/format/interval_text.lua --- a/env/format/interval_text.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/format/interval_text.lua Thu Jul 10 01:19:48 2014 +0200 @@ -7,7 +7,7 @@ :gsub("day", "{DAY}") :gsub("mons", "{MONS}") :gsub("mon", "{MON}") - :gsub("yeas", "{YEARS}") + :gsub("years", "{YEARS}") :gsub("year", "{YEAR}") if (options.mode == "time_left") then @@ -42,4 +42,4 @@ return _("#{interval_text} [interval]", { interval_text = interval_text }) end -end \ No newline at end of file +end diff -r a6c7bf07badb -r 701a5cf6b067 env/format/wiki_text.lua --- a/env/format/wiki_text.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/format/wiki_text.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,12 +1,38 @@ function format.wiki_text(wiki_text, formatting_engine) - local formatting_engine = formatting_engine or "rocketwiki" + + if not formatting_engine then + error("Formatting engine identifier required") + end + + local fe + + for i, fe_entry in ipairs(config.formatting_engines) do + if fe_entry.id == formatting_engine then + fe = fe_entry + break + end + end + + if not fe then + error("Formatting engine not found") + end + local html, errmsg, exitcode = assert( - extos.pfilter(wiki_text, config.formatting_engine_executeables[formatting_engine]) + extos.pfilter(wiki_text, fe.executable, table.unpack(fe.args or {})) ) + if exitcode > 0 then + trace.debug(html, errmsg) error("Wiki parser process returned with error code " .. tostring(exitcode)) elseif exitcode < 0 then + trace.debug(html, errmsg) error("Wiki parser process was terminated by signal " .. tostring(-exitcode)) end + + if fe.remove_images then + html = string.gsub(html, ']*>', '') + end + return html + end diff -r a6c7bf07badb -r 701a5cf6b067 env/model/has_rendered_content.lua --- a/env/model/has_rendered_content.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/model/has_rendered_content.lua Thu Jul 10 01:19:48 2014 +0200 @@ -47,7 +47,11 @@ rendered[class.table .. "_id"] = self.id end rendered.format = "html" - rendered.content = format.wiki_text(self[content_field_name], self.formatting_engine) + if self.formatting_engine then + rendered.content = format.wiki_text(self[content_field_name], self.formatting_engine) + else + rendered.content = self[content_field_name] + end rendered:save() -- and return it return rendered diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/actions.lua --- a/env/ui/actions.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/ui/actions.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,5 +1,5 @@ function ui.actions(content) - slot.select("head", function() + slot.select("actions", function() ui.container{ attr = { class = "actions" }, content = content } end) end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/bargraph.lua --- a/env/ui/bargraph.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/ui/bargraph.lua Thu Jul 10 01:19:48 2014 +0200 @@ -35,7 +35,7 @@ attr = { style = "width: " .. tostring(dlength_abs) .. "px; background-color: " .. bar.color .. ";", }, - content = function() slot.put(" ") end + content = "" } end ui.container{ @@ -43,7 +43,7 @@ class = "quorum", style = "width: 1px; background-color: " .. (args.quorum_color or "blue") ..";", }, - content = function() slot.put("") end + content = "" } length = dlength + 1 value = value - dlength @@ -59,7 +59,7 @@ attr = { style = "width: " .. tostring(value_abs) .. "px; background-color: " .. bar.color .. ";", }, - content = function() slot.put(" ") end + content = "" } end end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/contextbar.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/contextbar.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,17 @@ +function ui.contextbar ( arg1, arg2 ) + + local class = "sidebarSection" + local content + + if arg2 then + class = class .. " " .. arg1 + content = arg2 + else + content = arg1 + end + + slot.select ( "contextbar", function () + ui.container { attr = { class = class }, content = content } + end ) + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/delegation.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/delegation.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,19 @@ +function ui.delegation(to_member_id, to_member_name) + local text = _"delegates to" + ui.image{ + attr = { class = "delegation_arrow", alt = text, title = text }, + static = "delegation_arrow_24_horizontal.png" + } + + if to_member_id and to_member_name then + execute.view{ + module = "member_image", view = "_show", params = { + member_id = to_member_id, + class = "micro_avatar", + image_type = "avatar", + popup_text = to_member_name, + show_dummy = true + } + } + end +end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/filters.lua --- a/env/ui/filters.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/ui/filters.lua Thu Jul 10 01:19:48 2014 +0200 @@ -20,8 +20,12 @@ end local id = param.get_id_cgi() local params = param.get_all_cgi() + local class = "ui_filter_head" + if filter.class then + class = class .. " " .. filter.class + end ui.container{ - attr = { class = "ui_filter_head" }, + attr = { class = class }, content = function() slot.put(filter.label) for idx, option in ipairs(filter) do diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/raw_title.lua --- a/env/ui/raw_title.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/ui/raw_title.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,7 +1,20 @@ -function ui.raw_title(content) - slot.select("head", function() - ui.container{ attr = { class = "title" }, content = function() - slot.put(content) - end } - end) -end \ No newline at end of file +function ui.raw_title ( content ) + + slot.select ( "title", function () + + -- home link + ui.link { + module = "index", view = "index", + attr = { class = "home" }, + content = function () + ui.image { static = "icons/16/house.png" } + end + } + + slot.put ( " " ) + + slot.put ( content ) + + end ) + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/section.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/section.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,15 @@ +function ui.section ( arg1, arg2 ) + + local class = "section" + local content + + if arg2 then + class = class .. " " .. arg1 + content = arg2 + else + content = arg1 + end + + ui.container { attr = { class = class }, content = content } + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/sectionHead.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/sectionHead.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,15 @@ +function ui.sectionHead ( arg1, arg2 ) + + local class = "sectionHead" + local content + + if arg2 then + class = class .. " " .. arg1 + content = arg2 + else + content = arg1 + end + + ui.container { attr = { class = class }, content = content } + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/sectionRow.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/sectionRow.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,15 @@ +function ui.sectionRow ( arg1, arg2 ) + + local class = "sectionRow" + local content + + if arg2 then + class = class .. " " .. arg1 + content = arg2 + else + content = arg1 + end + + ui.container { attr = { class = class }, content = content } + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/sidebar.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/sidebar.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,17 @@ +function ui.sidebar ( arg1, arg2 ) + + local class = "sidebarSection" + local content + + if arg2 then + class = class .. " " .. arg1 + content = arg2 + else + content = arg1 + end + + slot.select ( "sidebar", function () + ui.container { attr = { class = class }, content = content } + end ) + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/sidebarHead.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/sidebarHead.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,15 @@ +function ui.sidebarHead ( arg1, arg2 ) + + local class = "sidebarHead" + local content + + if arg2 then + class = class .. " " .. arg1 + content = arg2 + else + content = arg1 + end + + ui.container { attr = { class = class }, content = content } + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/sidebarHeadWhatCanIDo.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/sidebarHeadWhatCanIDo.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,21 @@ +function ui.sidebarHeadWhatCanIDo () + ui.sidebarHead( function () + --ui.image{ attr = { class = "right icon24" }, static = "icons/48/info.png" } + ui.heading { + level = 2, content = _"What can I do here?" + } + end ) + if not app.session.member then + ui.sidebarSection( function() + ui.heading { level = 3, content = _"Closed user group" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function () + ui.link { + content = _"login to participate", + module = "index", view = "login" + } + end } + end } + end ) + end +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/sidebarSection.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/sidebarSection.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,15 @@ +function ui.sidebarSection ( arg1, arg2 ) + + local class = "sidebarRow" + local content + + if arg2 then + class = class .. " " .. arg1 + content = arg2 + else + content = arg1 + end + + ui.container { attr = { class = class }, content = content } + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/title.lua --- a/env/ui/title.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/env/ui/title.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,5 +1,31 @@ -function ui.title(content) - slot.select("head", function() - ui.container{ attr = { class = "title" }, content = content } - end) -end \ No newline at end of file +function ui.title ( content ) + + slot.select ( "title", function () + + -- home link + ui.link { + module = "index", view = "index", + attr = { class = "home", title = _"Home" }, + content = function () + ui.image { + attr = { class = "icon24", alt = title }, + static = "icons/48/home.png" + } + end + } + + if content then + ui.tag { attr = { class = "spacer" }, content = function() + slot.put ( " » " ) + end } + ui.tag { tag = "span", content = content } + else + ui.tag { attr = { class = "spacer" }, content = function() + slot.put ( " " ) + end } + ui.tag { tag = "span", content = _"Home" } + end + + end ) + +end diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/titleAdmin.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/titleAdmin.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,8 @@ +function ui.titleAdmin(title) + ui.title(function() + ui.link { module = "admin", view = "index", content = _"System administration" } + if title then + ui.tag { tag = "span", content = content } + end + end) +end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 env/ui/titleMember.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/ui/titleMember.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,17 @@ +function ui.titleMember(title, title2) + local member = app.session.member + if type(title) == "table" then + member = title + title = title2 + end + ui.title(function() + if member then + ui.link { module = "member", view = "show", id = member.id, content = member.name } + end + if title then + ui.tag { attr = { class = "member" }, content = function() + ui.tag{ tag = "span", content = title } + end } + end + end) +end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 env/util/help.lua --- a/env/util/help.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -function util.help(id, title) - if not app.session.member_id then - return - end - local setting_key = "liquidfeedback_frontend_hidden_help_" .. id - local setting = Setting:by_pk(app.session.member.id, setting_key) - if not setting then - ui.container{ - attr = { class = "help help_visible" }, - content = function() - ui.image{ - attr = { class = "help_icon" }, - static = "icons/16/help.png" - } - ui.container{ - attr = { class = "help_actions" }, - content = function() - ui.link{ - text = _"Hide this help message", - module = "help", - action = "update", - params = { - help_ident = id, - hide = true - }, - routing = { - default = { - mode = "redirect", - module = request.get_module(), - view = request.get_view(), - id = param.get_id_cgi(), - params = param.get_all_cgi() - } - } - } - end - } - local lang = locale.get("lang") - local basepath = request.get_app_basepath() - local file_name = basepath .. "/locale/help/" .. id .. "." .. lang .. ".txt.html" - local file = io.open(file_name) - if file ~= nil then - local help_text = file:read("*a") - if #help_text > 0 then - ui.container{ - attr = { class = "wiki" }, - content = function() - slot.put(help_text) - end - } - else - ui.field.text{ value = _("Empty help text: #{id}.#{lang}.txt", { id = id, lang = lang }) } - end - else - ui.field.text{ value = _("Missing help text: #{id}.#{lang}.txt", { id = id, lang = lang }) } - end - end - } - else - if util._hidden_helps == nil then - util._hidden_helps = {} - end - util._hidden_helps[#util._hidden_helps+1] = { - id = id, - title = title - } - end -end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 env/util/initiative_pie.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/util/initiative_pie.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,137 @@ +function util.initiative_pie(initiative, d, gap) + if not initiative.issue.closed or not initiative.admitted then + return + end + + if initiative.issue.voter_count == 0 or initiative.positive_votes == nil or initiative.negative_votes == nil then + return + end + + local first_preference_votes = initiative.first_preference_votes + if first_preference_votes == nil then + first_preference_votes = 0 + end + + local d = d or 100 + local gap = gap or d / 20 + + local r = d/2 + local r_circle = r - gap + + local function circle(p) + return + gap + 2 * r_circle * ( 1 + math.sin( 2 * math.pi * p ) ) / 2, + gap + 2 * r_circle * ( 1 - math.cos( 2 * math.pi * p ) ) / 2 + end + + local function getpath(start, stop) + local start_x, start_y = circle(start) + local stop_x, stop_y = circle(stop) + local large = stop - start > 0.5 and "1" or "0" + return "M" .. r .. "," .. r .. " " + .. "L" .. start_x .. ",".. start_y .. " " .. " " + .. "A" .. r_circle .. "," .. r_circle .. " 0 " .. large .. ",1 " .. stop_x .. "," .. stop_y .. " " + .. "z" + end + + local function uniPie(color, content) + ui.tag { + tag = "svg", + attr = { + class = "initiative_pie", + width = d .. "px", + height = d .. "px", + }, + content = function () + ui.tag { tag = "circle", attr = { + cx=r, cy=r, r=r_circle, fill = color, stroke = "#fff", ["stroke-width"] = "2" + }, content = function () ui.tag { tag = "title", content = content } end } + end + } + end + + local function piePiece(path, fill, content) + ui.tag { + tag = "path", + attr = { + d = path, + fill = fill, + stroke = "#fff", + ["stroke-width"] = "2", + ["stroke-linecap"] = "butt" + }, + content = function () + ui.tag { + tag = "title", + content = content + } + end + } + end + + local function pie(args) + local offset = args.offset or 0 + local list = {} + local sum = 0 + for i, element in ipairs(args) do + element.start = sum + offset + list[#list+1] = element + sum = sum + element.value + end + + for i, element in ipairs(list) do + if element.value == sum then + uniPie(element.fill, _(element.label, { count = element.value } )) + return + end + end + ui.tag { + tag = "svg", + attr = { + class = "initiative_pie", + width = d .. "px", + height = d .. "px" + }, + content = function () + table.sort(list, function (a, b) + return a.value < b.value + end ) + for i, element in ipairs(list) do + local path = getpath(element.start / sum, (element.start + element.value) / sum) + local content = _(element.label, { count = element.value }) + piePiece(path, element.fill, content) + end + end + } + end + + local yes1 = first_preference_votes + local yes = initiative.positive_votes - first_preference_votes + local neutral = initiative.issue.voter_count - initiative.positive_votes - initiative.negative_votes + local no = initiative.negative_votes + + local sum = yes1 + yes + neutral + no + + local q = initiative.issue.policy.direct_majority_num / initiative.issue.policy.direct_majority_den + + + local maxrot = sum * 7 / 12 - no + + local offset = 0 + + if maxrot > 0 then + offset = math.min ( + maxrot, + no * ( 1 / ( 1 / q - 1 ) -1 ) / 2 + ) + end + + pie{ + { value = yes1, fill = "#0a0", label = _"#{count} Yes, first choice" }, + { value = yes, fill = "#6c6", label = _"#{count} Yes, alternative choice" }, + { value = neutral, fill = "#ccc", label = _"#{count} Neutral" }, + { value = no, fill = "#c00", label = _"#{count} No" }, + offset = - offset + } + +end \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 env/util/micro_avatar.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/util/micro_avatar.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,49 @@ +function util.micro_avatar(member, member_name) + if type ( member ) == "number" then + member = { + id = member, + name = member_name + } + end + + function doit() + if config.fastpath_url_func then + ui.image{ + attr = { + title = member.name, + class = "microAvatar" + }, + external = config.fastpath_url_func(member.id, "avatar") + } + else + ui.image { + attr = { + title = member.name, + class = "microAvatar" + }, + module = "member_image", + view = "show", + extension = "jpg", + id = member.id, + params = { + image_type = "avatar" + } + } + end + ui.tag { tag = "span", content = member.name } + end + + ui.tag { + attr = { class = "microAvatar" }, + content = function () + if app.session:has_access("everything") then + ui.link { + module = "member", view = "show", id = member.id, + content = doit + } + else + ui.tag{ content = doit } + end + end + } +end diff -r a6c7bf07badb -r 701a5cf6b067 locale/Makefile --- a/locale/Makefile Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -PATH:=$(PATH):/opt/rocketwiki/ - -DIRS = help -HTML_SOURCE := $(foreach DIR,$(DIRS),$(wildcard $(DIR)/*.txt)) -HTML_HELP := $(HTML_SOURCE:.txt=.txt.html) -TARGET = all - - -%.txt.html: %.txt - rocketwiki-lqfb < $< > $@ - - -help_html: $(HTML_HELP) - -clean: - rm -f $(HTML_HELP) - -all: help_html diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/area.show.de.txt --- a/locale/help/area.show.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -= Themenbereich = - -Hier finden sich jeweils unter: -- **Letzte Ereignisse:** Alle Ereignisse im Themenbereich -- **Offene Themen:** Alle Themen des Themenbereichs, die zur Zeit offen sind, also Neu, in Diskussion, Eingefroren oder in Abstimmung -- **Geschlossene Themen:** Alle Themen des Themenbereichs, die bereits abgestimmt sind oder die abgebrochen wurden -- **Teilnehmer:** Stimmberechtigte, die sich dazu entschieden haben, sich im Themenbereich einzubringen -- **Delegationen:** Auf Themenbereichsebene gesetzte Delegationen (Delegationen auf darüberliegender Gliederungsebene, sowie Delegationen auf darunterliegender Themenebene werden hier nicht aufgeführt) - -Sofern die Stimmberechtigung in der Gliederung vorhanden ist, kann man sich durch einen Klick auf "An diesem Themengebiet teilnehmen" als Teilnehmer des Themengebietes eintragen. Dies hat folgende Konsequenzen: -- Der jeweilige Themenbereich wird auf der Startseite unter "Meine Themengebiete" angezeigt. -- Man zählt zur Grundgesamtheit der Diskussionsteilnehmer von Themen im Themengebiet. Dies wirkt sich auf das von Initiativen zu erreichende Unterstützerquorum aus. -- Benachrichtigungen zu Ereignissen im jeweiligen Themenbereich werden verschickt, sofern die Benachrichtigungseinstellungen entsprechend eingestellt sind. Die Benachrichtigungseinstellungen finden sich unter "Einstellungen" im Benutzermenü ganz rechts oben. - -Delegationen im Themenbereich wirken sich auf alle Themen aus, bei denen keine abweichende Delegationseinstellung vermerkt ist. Ist keine Delegationseinstellung im Themenbereich vorhanden, gilt ggf. eine Delegation auf Gliederungsebene. Bei eigenem Interesse an einem Thema, wird eine eventuell vorhandene Delegation zunächst ausgesetzt. Ebenso werden Delegationen dort ausgesetzt, wo man selbst an der Endabstimmung teilnimmt. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/area.show.el.txt --- a/locale/help/area.show.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -==Τομέας== -Παρουσίαση ενός τομέα με τα θέματα που υπάγονται σ' αυτόν. Μπορείτε να αναθέσετε έναν ολόκληρο τομέα σε κάποιο άλλο μέλος από τις επαφές σας, ώστε να σας αντιπροσωπεύει με την ψήφο του στα θέματα του τομέα αυτού. Μπορείτε να ακυρώσετε ή να αλλάξετε τέτοια ανάθεση οποιαδήποτε στιγμή, για όλο τον τομέα ή μόνο για συγκεκριμένα θέματα. - -Εδώ μπορείτε επίσης να δηλώσετε συμμετοχή στον τομέα ή και να ανοίξετε ένα νέο θέμα και να εισηγηθείτε μία πρωτοβουλία. - -Η δήλωση συμμετοχής στον τομέα έχει τις εξής συνέπειες: -- Ο τομέας θα εμφανίζεται στην κεντρική σας σελίδα κάτω από το "Οι τομείς μου" -- Προσμετράστε στο βασικό σύνολο για τις συζητήσεις των θεμάτων. Αυτό έχει επιπτώσεις στην απαρτία υποστηρικτών που πρέπει να συμπληρώσουν οι πρωτοβουλίες. -- Θα λαμβάνετε ειδοποιήσεις μέσω email για τα συμβάντα στον τομέα, εφόσον το έχετε επιλέξει και στις ρυθμίσεις ειδοποιήσεων. Μπορείτε να δείτε και να αλλάξετε τις ρυθμίσεις ειδοποιήσεων πηγαίνοντας στο "Επιλογές", στο μενού χρήστη στην πάνω δεξιά γωνία. - -=Συμβάντα= -Παρουσίαση των γεγονότων στον τομέα, με χρονολογική σειρά. - -=Θέματα= -Όλα τα θέματα που ανήκουν σ' αυτόν τον τομέα, διαχωρισμένα σε <<κλειστά>> που έχουν καταλήξει και σε <<ανοιχτά>>, που βρίσκονται σε διαβούλευση ή ψηφοφορία ή σε κάποιο άλλο στάδιο. - -=Συμμετέχοντες= -Κατάλογος όλων των μελών που έχουν δηλώσει συμμετοχή σε αυτόν τον τομέα. - -=Αναθέσεις= -Παρουσίαση των αναθέσεων για αυτόν τον τομέα. Δείχνει τα μέλη και τους αντιπροσώπους που έχουν ορίσει. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/area.show.en.txt --- a/locale/help/area.show.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -= Subject area = - -Here you find: -- **Latest events:** Events in this subject area -- **Open issues:** Issues of this subject area, which are currently open, i.e. new, in discussion, frozen or for voting -- **Closed issues:** Issues of this subject area, where voting has been finished, or which have been canceled -- **Participants:** Eligible voters, who decided to participate in this subject area -- **Delegations:** Delegation settings of other members for this subject area (unit delegations and issue delegations are not listed here) - -As long as you're an eligible voter, you can indicate that you want to participate in this subject area. Click on "Participate in this area", if you want to do that. This has the following consequences: -- The subject area will be shown on your homepage under the tab "My areas". -- You are counted for the basic population for issue discussions. This has an impact on the supporter quorum, which initiatives have to reach. -- E-mail notifies about events in the subject area will be sent, as long as your notification settings are configured respectively. Your notification settings can be changed by clicking on "Settings" in the user menu at the upper right corner. - -Your delegation of the subject area has an effect on all issues, where no divergent issue delegation has been set by you. When you do not set a delegation in the subject area, your delegation for the organizational unit may be in effect. If you're interested in an issue yourself, then potentially existent delegations will be postponed until voting. Voting on an issue cancels an existent delegation. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/area.show.zh-Hans.txt --- a/locale/help/area.show.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -= 领域 = - -您所看到的: -- **最新动态:** 此领域的新动态 -- **开放性议题:** 目前在此领域仍开放的议题,可能处于新增、讨论中、底定或表决阶段。 -- **已结案议题:** 在此领域已经表决或被撤销的议题 -- **参与者:** 决定参与此领域的合格投票人 -- **委任清单:** 本领域的其他参与者所设置的委任(单位及议题委任不在此列) - -只要您是一个合格投票人,您可设定您是否要参与此领域。若您有此意愿,请点选「参与此领域」。之后将有下列变化: -- 此领域将被显示在您首页的「我的领域」标签下。 -- 您将被计入此议题的讨论人数。这将影响提案必须通过的支持者决定门槛。 -- 只要您的通知设定允许,您将收到此领域的动态电邮通知。您可点选右上方使用者目录的「设定」连结以更改通知设定。 - -您对此领域的委任将影响所有您未设定个别委任的议题,当您不对此领域设定委任,您对组织单位的委任设定将生效。若您关心个别议题,则潜在存在的委任将延后至表决。对个别议题进行表决则取消已设定的委任。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/area.show.zh-TW.txt --- a/locale/help/area.show.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -= 領域 = - -您所看到的: -- **最新動態:** 此領域的新動態 -- **開放性議題:** 目前在此領域仍開放的議題,可能處於新增、討論中、底定或表決階段。 -- **已結案議題:** 在此領域已經表決或被撤銷的議題 -- **參與者:** 決定參與此領域的合格投票人 -- **委任清單:** 本領域的其他參與者所設置的委任(單位及議題委任不在此列) - -只要您是一個合格投票人,您可設定您是否要參與此領域。若您有此意願,請點選「參與此領域」。之後將有下列變化: -- 此領域將被顯示在您首頁的「我的領域」標籤下。 -- 您將被計入此議題的討論人數。這將影響提案必須通過的支持者決定門檻。 -- 只要您的通知設定允許,您將收到此領域的動態電郵通知。您可點選右上方使用者目錄的「設定」連結以更改通知設定。 - -您對此領域的委任將影響所有您未設定個別委任的議題,當您不對此領域設定委任,您對組織單位的委任設定將生效。若您關心個別議題,則潛在存在的委任將延後至表決。對個別議題進行表決則取消已設定的委任。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/contact.list.de.txt --- a/locale/help/contact.list.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=persönliche Kontaktliste= -Um sie schneller auffinden zu können, kann man andere Mitglieder deiner persönlichen Kontaktliste hinzufügen. Auf der Profilseite des jeweiligen Mitglieds findet sich ein Link zum Hinzufügen. Falls man diesen Kontakt veröffentlicht, können andere sehen, dass dieses Mitglied auf der Kontaktliste vermerkt wurde. - -**Wichtig:** Zur Verbesserung des Bedienkomforts wird beim Delegieren die persönliche Kontaktliste angezeigt. Um an ein Mitglied delegieren zu können, musst es zunächst als Kontakt hinzugefügt werden. Das Löschen eines Kontaktes führt jedoch nicht zum Widerruf der Delegation. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/contact.list.el.txt --- a/locale/help/contact.list.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -==Προσωπική λίστα επαφών== -Μπορείτε να προσθέσετε μέλη στις επαφές σας ώστε να τα βρίσκετε γρηγορότερα. Αυτό γίνεται με ένα σύνδεσμο που θα βρείτε στη σελίδα προφίλ του κάθε μέλους. - -//Για να δείτε όλα τα εγγεγραμμένα μέλη πηγαίνετε στην κεντρική σελίδα και πατήστε στο <<Μέλη>>.// - -=Δημοσίευση= -Η λίστα των επαφών σας είναι προσωπική και δεν εμφανίζεται σε άλλους. Εάν επιλέξετε να δημοσιεύσετε κάποια από τα μέλη στις επαφές σας, τα μέλη αυτά θα εμφανίζονται δημόσια στη λίστα των επαφών σας. - -=Αναθέσεις= -Για να μπορέσετε να αναθέσετε κάποια <<ενότητα>>, <<τομέα>> ή <<θέμα>> σε ένα μέλος θα πρέπει να το προσθέσετε πρώτα στις επαφές σας ώστε να εμφανίζεται στη λίστα της εντολής ανάθεσης. Αφαίρεση μελών από τις επαφές σας δεν ακυρώνει αναθέσεις που μπορεί να έχουν γίνει. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/contact.list.en.txt --- a/locale/help/contact.list.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=personal list of contacts= -In order to find other members more quickly, you can add them to your personal list of contacts. On the profile page of the respective member you will find a link for doing so. If you publish a contact, others can see this member as listed on your list of contacts. - -**Important:** For improved ease-of-use your list of contacts will be shown to you when you delegate. In order to delegate to a member, you must first add him or her to your contacts. Removing a contact does not revoke the delegation, though. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/contact.list.eo.txt --- a/locale/help/contact.list.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=Persona kontaktlisto= -Vi povas aldoni aliajn membrojn al via persona kontaktlisto, por ke vi trovu ilin pli rapide. En la profilpaĝo de la respektiva membro vi trovas ligilon por aldoni. Se vi publikigas kontakton, aliaj povas vidi, ke tiu ĉi membro estas en via kontaktlisto. - -**Grave:** Por pliigi vian komforton, oni montras al vi dum delegado vian personan kontaktliston. Por povi delegi al membro vi devas unue aldoni lin kiel kontakton. Nuligi kontakton tamen ne kaŭzas revokon de la delegacio. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/contact.list.zh-Hans.txt --- a/locale/help/contact.list.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=个人通讯录列表= -为了更快速找到其他成员,您可将他们加入您的个人通讯录。您可在个别成员的个人简介页找到连结以加入。若您公开一个连络人,其他人将可看到这位成员被列在您的通讯录中。 - -**重要事项:** 为了使用方便,您的通讯录列表将会在您指定委任时显示。要委任一位成员,您必须先加他为您的联络人。但将委任人自通讯录移除并不会撤回委任。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/contact.list.zh-TW.txt --- a/locale/help/contact.list.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=個人通訊錄列表= -為了更快速找到其他成員,您可將他們加入您的個人通訊錄。您可在個別成員的個人簡介頁找到連結以加入。若您公開一個連絡人,其他人將可看到這位成員被列在您的通訊錄中。 - -**重要事項:** 為了使用方便,您的通訊錄列表將會在您指定委任時顯示。要委任一位成員,您必須先加他為您的聯絡人。但將委任人自通訊錄移除並不會撤回委任。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.area.de.txt --- a/locale/help/delegation.new.area.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Delegation für diesen Themenbereich = - -Man kann die eigene Stimme für diesen Themenbereich (unabhängig von der Mitgliedschaft im Themenbereich) an eine Person in der persönlichen Kontaktliste delegieren. Diese Delegation hat gegenüber einer eventuell vorhandenen Gliederungsdelegation Vorrang, gilt jedoch nur dann, wenn keine eigene Beteiligung am Thema besteht bzw. nicht selbst abgestimmt wird und man für das jeweilige Thema keine themenspezifische Delegation erteilt hat. - -**Achtung:** Delegieren kann man nur an Mitglieder in der eigenen Kontaktliste. Um ein Mitglied zur Kontaktliste hinzuzufügen ist die Seite des jeweiligen Mitglieds aufzurufen. Diese findet man z.B. in der jeweiligen Gliederung unter dem Reiter ,,Stimmberechtigte''. Durch einen Klick auf den Benutzer gelangt man zur Seite des jeweiligen Mitglieds, auf der man dieses Mitglied zu den persönlichen Kontakten hinzufügen kann. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.area.el.txt --- a/locale/help/delegation.new.area.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=Ανάθεση τομέα= -Μπορείτε να εκχωρήσετε την ψήφο σας για αυτόν τον τομέα (ανεξάρτητα από τη συμμετοχή σας στον τομέα) σε ένα άτομο από τη λίστα επαφών σας. Μπορείτε να προσθέσετε άτομα στις επαφές σας πηγαίνοντας στην περιοχή <<Μέλη>>, στην κεντρική σελίδα ή στην περιοχή <<Συμμετέχοντες>> του τρέχοντος τομέα. - -Η ανάθεση αυτή υπερισχύει μιας πιθανής καθολικής ανάθεσης αλλά μόνο στην περίπτωση που δεν συμμετέχετε προσωπικά και όταν πρόκειται για κάποιο <<θέμα>> το οποίο δεν έχετε αναθέσει πιο συγκεκριμένα. Για να αναθέσετε συγκεκριμένα θέματα του τομέα, παρακαλώ πηγαίνετε στη σελίδα τους. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.area.en.txt --- a/locale/help/delegation.new.area.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Delegation for this area = - -You can delegate your vote for this area (independent of your membership in the area) to a person on your contact list. This delegation takes precedence over a potentially existing global delegation, but only, if you don't participate yourself and if you have not given a issue-specific delegation for the respective issue. Please go to the respective issue page for making issue-specific delegations. - -**Notice:** You can only delegate to members, who you have added to your list of contacts. You can find other members under the tabulator ""Eligible voters"" in their corresponding unit. Click on the member to visit their member page, then click on ""Add to my contacts"" to add this member to your personal contact list. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.area.eo.txt --- a/locale/help/delegation.new.area.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Delegacio pri tiu ĉi temaro = - -Vi povas delegi vian voĉon por tiu ĉi temaro (sendepende de via membreco en tiu ĉi temaro) al persono en via kontaktlisto. Tiu ĉi delegacio rangas antaŭ ebla ĝenerala delegacio, sed nur se vi ne mem partoprenas kaj vi ne delegis teman delegacion pri la respektiva temo. Por tema delegado bonvolu ŝanĝi al la respektiva tempaĝo. Vi povas delegi nur al membroj de via kontaktlisto. - -**Notice:** You can only delegate to members, who you have added to your list of contacts. You can find other members under the tabulator ""Eligible voters"" in their corresponding unit. Click on the member to visit their member page, then click on ""Add to my contacts"" to add this member to your personal contact list. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.area.zh-Hans.txt --- a/locale/help/delegation.new.area.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 领域委任 = - -不论您是否有此领域的成员身份,您可委任您的表决给您通讯录中的一位联络人。此委任,在您本身不参与表决或您并未对个别议题指定委任的状况下,会优先于一个可能已存在的全面委任。若您要对个别议题进行委任,请前往该议题页面。 - -**注意:** 您只可委任给您已加入通讯录的成员。 ?您可在各相关单位页面的「合格投票人」页签找到其他成员。点击各成员连结以拜访他们的成员专页,然后点击「加入通讯录」将此成员加入您的个人联络人列表。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.area.zh-TW.txt --- a/locale/help/delegation.new.area.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 領域委任 = - -不論您是否有此領域的成員身份,您可委任您的表決給您通訊錄中的一位聯絡人。此委任,在您本身不參與表決或您並未對個別議題指定委任的狀況下,會優先於一個可能已存在的全面委任。若您要對個別議題進行委任,請前往該議題頁面。 - -**注意:** 您只可委任給您已加入通訊錄的成員。您可在各相關單位頁面的「合格投票人」頁籤找到其他成員。點擊各成員連結以拜訪他們的成員專頁,然後點擊「加入通訊錄」將此成員加入您的個人聯絡人列表。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.issue.de.txt --- a/locale/help/delegation.new.issue.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -= Delegation für dieses Thema = -Eine Delegation zu diesem Thema geht einer eventuell vorhandenen globalen Delegation und/oder Delegation für den übergeordneten Themenbereich vor. Bei angemeldetem Interesse werden ausgehende Delegationen während der Phasen ,,Neu'', ,,Diskussion'' und ,,Eingefroren'' ausgesetzt, gelten aber in der Endabstimmung, sofern nicht selbst abgestimmt wird. - -**Achtung:** Delegieren kannst man nur an Mitglieder in der eigenen Kontaktliste. Um ein Mitglied zur Kontaktliste hinzuzufügen ist die Seite des jeweiligen Mitglieds aufzurufen. Diese findet man z.B. in der jeweiligen Gliederung unter dem Reiter ,,Stimmberechtigte''. Durch einen Klick auf den Benutzer gelangt man zur Seite des jeweiligen Mitglieds, auf der man dieses Mitglied zu den persönlichen Kontakten hinzufügen kann. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.issue.el.txt --- a/locale/help/delegation.new.issue.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=Ανάθεση θέματος= -Μπορείτε να εκχωρήσετε την ψήφο σας για αυτό το θέμα σε κάποιο άτομο από τη λίστα επαφών σας. Για να προσθέσετε άτομα στις επαφές σας πηγαίνετε στην περιοχή <<Μέλη>>, στην κεντρική σελίδα. - -Η ανάθεση αυτή υπερισχύει μιας πιθανής καθολικής ανάθεσης ή ανάθεσης τομέα ή ενότητας που μπορεί να ισχύει. Εάν έχετε δηλώσει το ενδιαφέρον σας για αυτό το θέμα, η εξερχόμενη ανάθεση //(δηλαδή όταν εσείς επιλέγετε κάποιον άλλο ως αντιπρόσωπό σας για το <<θέμα>>)// θα ανασταλεί κατά το στάδιο συζήτησης, αλλά θα είναι ενεργή κατά την ψηφοφορία. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.issue.en.txt --- a/locale/help/delegation.new.issue.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Delegation for this issue = - -A delegation for this issue takes precedence over a potentially existing global delegation and/or a delegation for the superior area. If you added your interest outgoing delegations will be suspended during the discussion phase, but will be active during the final voting. You can only delegate to members on your contact list. You can extend the contact list anytime in the ,,Members'' area. - -**Notice:** You can only delegate to members, who you have added to your list of contacts. You can find other members under the tabulator ""Eligible voters"" in their corresponding unit. Click on the member to visit their member page, then click on ""Add to my contacts"" to add this member to your personal contact list. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.issue.eo.txt --- a/locale/help/delegation.new.issue.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Delegacio pri tiu ĉi temo = - -Delegacio pri tiu ĉi temo rangas antaŭ ebla ĝenerala delegacio kaŭ delegacio pri la supera temaro. Kaze de anoncita intereso, la elirantaj delegacioj estas malebligitaj dum la diskutfazo, sed validas ĉe la fina voĉdono. Vi povas delegi nur al membroj de via kontaktlisto. - -**Notice:** You can only delegate to members, who you have added to your list of contacts. You can find other members under the tabulator ""Eligible voters"" in their corresponding unit. Click on the member to visit their member page, then click on ""Add to my contacts"" to add this member to your personal contact list. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.issue.zh-Hans.txt --- a/locale/help/delegation.new.issue.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 议题委任 = - -对此议题的委任会优先于可能已存在的全面委任或更高阶的领域委任。若您关心此议题,则所送出的委任将在讨论期被暂停,直到最后表决时再次启用。您只能委任给您通讯录中的联络人。您可在任何时候自「成员」页面延伸您的通讯录。 - -**注意:** 您只可委任给您已加入通讯录的成员。 ?您可在各相关单位页面的「合格投票人」页签找到其他成员。点击各成员连结以拜访他们的成员专页,然后点击「加入通讯录」将此成员加入您的个人联络人列表。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.issue.zh-TW.txt --- a/locale/help/delegation.new.issue.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 議題委任 = - -對此議題的委任會優先於可能已存在的全面委任或更高階的領域委任。若您關心此議題,則所送出的委任將在討論期被暫停,直到最後表決時再次啟用。您只能委任給您通訊錄中的聯絡人。您可在任何時候自「成員」頁面延伸您的通訊錄。 - -**注意:** 您只可委任給您已加入通訊錄的成員。您可在各相關單位頁面的「合格投票人」頁籤找到其他成員。點擊各成員連結以拜訪他們的成員專頁,然後點擊「加入通訊錄」將此成員加入您的個人聯絡人列表。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.unit.de.txt --- a/locale/help/delegation.new.unit.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Delegation für Gliederung = - -Die Delegation für eine Gliederung gilt immer dann, wenn man sich nicht selbst beteiligt und es keine Delegation auf der Ebene des jeweiligen Themenbereichs oder des Themas gibt. Beachte, dass Delegationen für eine übergeordnete Gliederungsebene nicht automatisch für untergeordnete Gliederungsebenen gelten. - -**Achtung:** Delegieren kannst man nur an Mitglieder in der eigenen Kontaktliste. Um ein Mitglied zur Kontaktliste hinzuzufügen ist die Seite des jeweiligen Mitglieds aufzurufen. Diese findet man z.B. in der jeweiligen Gliederung unter dem Reiter ,,Stimmberechtigte''. Durch einen Klick auf den Benutzer gelangt man zur Seite des jeweiligen Mitglieds, auf der man dieses Mitglied zu den persönlichen Kontakten hinzufügen kann. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.unit.el.txt --- a/locale/help/delegation.new.unit.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -=Ανάθεση ενότητας= -Μπορείτε να εκχωρήσετε την ψήφο σας για αυτήν την ενότητα σε κάποιο άτομο από τη λίστα επαφών σας. Για να προσθέσετε άτομα στις επαφές σας πηγαίνετε στην περιοχή <<Μέλη>>, στην κεντρική σελίδα. - -Η ανάθεση αυτή ισχύει σε κάθε περίπτωση που δεν συμμετέχετε προσωπικά και δεν υπάρχει πιο εξειδικευμένη ανάθεση σε επίπεδο <<τομέα>> ή <<θέματος>>. - -Η ανάθεση μίας ενότητας δεν κληρονομείται αυτόματα από πιθανές υπο-ενότητές της. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.unit.en.txt --- a/locale/help/delegation.new.unit.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Unit delegation = - -A unit delegation is always active if you don't participate yourself and there is no delegation on the level of the respective area or issue. Note that unit delegations for a superordinate unit are not automatically inherited to subdivisions. - -**Notice:** You can only delegate to members, who you have added to your list of contacts. You can find other members under the tabulator ""Eligible voters"" in their corresponding unit. Click on the member to visit their member page, then click on ""Add to my contacts"" to add this member to your personal contact list. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.unit.zh-Hans.txt --- a/locale/help/delegation.new.unit.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 单位委任 = - -若您本身并未直接参与(关心)特定议题或是设定特定领域或议题的委任,单位委任就总是有效的。请注意对一个较高层的单位委任并不自动传承给其次级单位。 - -**注意:** 您只可委任给您已加入通讯录的成员。 ?您可在各相关单位页面的「合格投票人」页签找到其他成员。点击各成员连结以拜访他们的成员专页,然后点击「加入通讯录」将此成员加入您的个人联络人列表。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/delegation.new.unit.zh-TW.txt --- a/locale/help/delegation.new.unit.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 單位委任 = - -若您本身並未直接參與(關心)特定議題或是設定特定領域或議題的委任,單位委任就總是有效的。請注意對一個較高層的單位委任並不自動傳承給其次級單位。 - -**注意:** 您只可委任給您已加入通訊錄的成員。您可在各相關單位頁面的「合格投票人」頁籤找到其他成員。點擊各成員連結以拜訪他們的成員專頁,然後點擊「加入通訊錄」將此成員加入您的個人聯絡人列表。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.check_delegations.de.txt --- a/locale/help/index.check_delegations.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Dieses System ist so konfiguriert, dass Teilnehmer aufgefordert werden ihre Delegationen für Gliederungen und Themengebiete regelmäßig zu überprüfen und zu bestätigen. Hierzu sind diese in der folgenden Liste aufgeführt. Ein Klick auf "Delegationsprüfung abschließen" vervollständigt den Vorgang. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.check_delegations.en.txt --- a/locale/help/index.check_delegations.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -This system is configured to advise members to check and confirm their unit and area delegations regularly. To do so please check your outgoing delegations for units and areas as listed below. Click on "Finish delegation check" to complete this procedure. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.check_delegations_hard.de.txt --- a/locale/help/index.check_delegations_hard.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Dieses System ist so konfiguriert, dass Teilnehmer gezwungen sind ihre Delegationen für Gliederungen und Themengebiete regelmäßig zu überprüfen und zu bestätigen. Hierzu sind diese in der folgenden Liste aufgeführt. Ein Klick auf "Delegationsprüfung abschließen" vervollständigt den Vorgang. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.check_delegations_hard.en.txt --- a/locale/help/index.check_delegations_hard.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -This system is configured to enforce members to check and confirm their unit and area delegations regularly. To do so please check your outgoing delegations for units and areas as listed below. Click on "Finish delegation check" to complete this procedure. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.download.de.txt --- a/locale/help/index.download.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Download der Datenbank = - -Im Interesse der Nachvollziehbarkeit ist es jedem Mitglied möglich, eine Kopie der gesamten Datenbank herunterzuladen. Hierbei werden jedoch aus Sicherheits- und Datenschutzgründen bestimmte Informationen (z.B. Passwörter und E-Mail-Adressen) entfernt. Das Dateiformat ist gzip-komprimiertes SQL für die Datenbank PostgreSQL. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.download.el.txt --- a/locale/help/index.download.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -==Λήψη βάσης δεδομένων== -Οποιοδήποτε μέλος μπορεί να κατεβάσει ένα αντίγραφο ολόκληρης της βάσης δεδομένων και να το ελέγξει. Για λόγους ασφαλείας και προστασίας προσωπικών δεδομένων, κάποια στοιχεία (π.χ. κωδικοί πρόσβασης και διευθύνσεις email) θα λείπουν. - -Τα δεδομένα είναι σε μορφή SQL (για PostgreSQL) και είναι συμπιεσμένα με το gzip. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.download.en.txt --- a/locale/help/index.download.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Database download = - -For auditability reasons all members can download a copy of the entire database. But for security and data privacy reasons certain data (e.g. passwords and email addresses) will be lacking. The data format is SQL as used for the PostgreSQL database compressed with gzip. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.download.eo.txt --- a/locale/help/index.download.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Elŝuto de la datumbazo = - -Por plua evaluado ĉiu membro povas elŝuti kopion de la tuta datumbazo. Ĉe tio tamen certaj informoj (ekzemple pasvortoj kaj retpoŝtadresoj) estas forviŝitaj pro sekurecaj kaj datumprotektaj kialoj. La datumformato estas gzip-kunpremita SQL por la datumbazo PostgreSQL. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.download.zh-Hans.txt --- a/locale/help/index.download.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 下载资料库 = - -为了可审查性考量,所有成员可下载整个资料库的一份备份。但为了安全及资料隐私考量,某些资料(例如:密码及电邮地址)将从缺。资料格式为如同 PostgreSQL 资料库所使用的 SQL,并使用 gzip 压缩。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.download.zh-TW.txt --- a/locale/help/index.download.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 下載資料庫 = - -為了可審查性考量,所有成員可下載整個資料庫的一份備份。但為了安全及資料隱私考量,某些資料(例如:密碼及電郵地址)將從缺。資料格式為如同 PostgreSQL 資料庫所使用的 SQL,並使用 gzip 壓縮。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.index.de.txt --- a/locale/help/index.index.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -= Willkommen bei LiquidFeedback und auf deiner Startseite = -Überall im System finden sich Kästen wie dieser mit Hilfetexten. Man kann jeden Hilfetext mit einem Klick auf "Diesen Hilfetext ausblenden" rechts oben im gelben Kasten ausblenden und durch einen Klick auf das kleine blaue Fragezeichen oben in der Menüzeile wieder einblenden. - -Unten finden sich folgende Ansichten: -- **Startseite:** Eine Unterauswahl zwischen: --- **Meine Themengebiete:** Themenbereiche, an denen teilgenommen wird --- **Alle Themengebiete in meinen Gliederungen:** alle Themenbereiche in Gliederungen mit Stimmberechtigung --- **Alle Gliederungen:** Alle Gliederungen, unabhängig von der Stimmberechtigung -- **Letzte Ereignisse:** Ereignisse aus den eigenen Themenbereichen und Themen sowie die globale Zeitlinie -- **Offene Themen:** Alle Themen, die zur Zeit offen sind, also Neu, in Diskussion, Eingefroren oder in Abstimmung -- **Geschlossene Themen:** Alle Themen, die bereits abgestimmt sind oder die abgebrochen wurden -- **Mitglieder:** Alle aktiven Mitglieder. Nach einem Klick auf ein bestimmtes Mitglied kann man dieses zur persönlichen Kontaktliste hinzufügen, um später an dieses Mitglied delegieren zu können. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.index.el.txt --- a/locale/help/index.index.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -=Καλώς ήρθατε στο Liquid Feedback και στην αρχική σας σελίδα= -Αυτά τα κίτρινα πλαίσια με τα βοηθητικά κείμενα θα σας ακολουθούν μέχρι να τα αποκρύψετε σταδιακά, ενώ αν χρειαστεί μπορείτε να τα επαναφέρετε εύκολα κάνοντας κλικ στο εικονίδιο βοήθειας. - -Εδώ θα βρείτε: - -- Κεντρική Σελίδα --- Τους τομείς που σας ενδιαφέρουν --- Όλους τους τομείς στις ενότητες που έχετε δικαίωμα ψήφου --- Όλες τις ενότητες -- Πρόσφατα συμβάντα από τους τομείς που σας ενδιαφέρουν καθώς και σε όλο το σύστημα -- Όλα τα θέματα, διαχωρισμένα σε <<κλειστά>> που έχουν καταλήξει και σε <<ανοιχτά>> που βρίσκονται σε διαβούλευση ή ψηφοφορία ή σε κάποιο άλλο στάδιο. -- Όλα τα ενεργά μέλη, τα οποία μπορείτε να προσθέσετε στις επαφές σας ώστε να μπορείτε να τους ορίσετε ως αντιπροσώπους σας αναθέτοντάς τους κάποια ενότητα, τομέα ή συγκεκριμένο θέμα. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.index.en.txt --- a/locale/help/index.index.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -= Welcome to LiquidFeedback and your homepage = -All over the system, you'll find these boxes with help texts. You can switch off each help text, by clicking on "hide this help message" in the upper right corner of the yellow box, and switch it on again, by clicking on the small blue question mark in the menu bar above. - -Below you find: -- **Home:** --- **My areas:** subject areas you want to participate in --- **All areas in my units:** All subject areas of those organizational units you're eligible voter in --- **All units:** All organizational units -- **Latest events:** Events in your subject areas and your issues, as well as the global timeline -- **Open issues:** All issues, which are currently open, i.e. new, in discussion, frozen or for voting -- **Closed issues:** All issues, where voting has been finished, or which have been canceled -- **Members:** All active members. After you clicking on a particular member, you can add this member to your personal contact list, in order to be able to delegate to that member. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.index.zh-Hans.txt --- a/locale/help/index.index.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -= 欢迎莅临 LiquidFeedback 及您的首页 = -在整个系统内,您将看到这些说明文件的框架。您可点击黄色框架右上角的「隐藏此说明文件」来个别关闭说明文件,或点击上方选单栏的小蓝问号圈以再次启用。 - -以下您将看到: -- **首页:** --- **我的领域:** 您想参与的主题领域 --- **我单位中所有领域:** 所有您为合格投票人的组织单位中的主题领域 --- **所有单位:** 所有的组织性单位 -- **最新动态:** 您的领域及议题的动态,以及完整的时间轴显示。 -- **开放性议题:** 所有目前仍开放的议题,意即:递交期议题、讨论期议题、底定期议题或表决中议题。 -- **已结案议题:** 所有表决已完成或是已被取消的议题。 -- **成员** 所有活动的成员。您可点选特定成员,加入您的通讯录,便得以委任给该成员。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/index.index.zh-TW.txt --- a/locale/help/index.index.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -= 歡迎蒞臨 LiquidFeedback 及您的首頁 = -在整個系統內,您將看到這些說明文件的框架。您可點擊黃色框架右上角的「隱藏此說明文件」來個別關閉說明文件,或點擊上方選單欄的小藍問號圈以再次啓用。 - -以下您將看到: -- **首頁:** --- **我的領域:** 您想參與的主題領域 --- **我單位中所有領域:** 所有您為合格投票人的組織單位中的主題領域 --- **所有單位:** 所有的組織性單位 -- **最新動態:** 您的領域及議題的動態,以及完整的時間軸顯示。 -- **開放性議題:** 所有目前仍開放的議題,意即:遞交期議題、討論期議題、底定期議題或表決中議題。 -- **已結案議題:** 所有表決已完成或是已被取消的議題。 -- **成員** 所有活動的成員。您可點選特定成員,加入您的通訊錄,便得以委任給該成員。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.add_initiator.de.txt --- a/locale/help/initiative.add_initiator.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Initiator einladen = - -Hier kannst du eine Person aus deiner Kontaktliste zur gleichberechtigten Mitarbeit am Entwurf einladen. Der eingeladene muss die Einladung erst akzeptieren, bevor er als weiterer Initiator gilt (und angezeigt wird). **Vorsicht:** Alle Initiatoren haben die gleichen Rechte und können andere Initiatoren entfernen. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.add_initiator.el.txt --- a/locale/help/initiative.add_initiator.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -==Πρόσκληση νέου εισηγητή== -Εδώ μπορείτε να προσκαλέσετε ένα άτομο από τη λίστα επαφών σας για να συνεργαστείτε με ίσα δικαιώματα στο προσχέδιο. Το μέλος που θα καλέσετε πρέπει πρώτα να αποδεχτεί την πρόσκληση για να γίνει και να εμφανίζεται ως εισηγητής. - -**Προσοχή:** Όλοι οι εισηγητές έχουν τα ίδια δικαιώματα και μπορούν να αφαιρέσουν άλλους εισηγητές. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.add_initiator.en.txt --- a/locale/help/initiative.add_initiator.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Invite initiator = - -Here you can invite a person on your contact list to collaborate with equal rights on the draft. The invited member must first accept the invitation in order to become an initiator (and be displayed as such). **Attention:** All initiators have the same rights and can remove other initiators. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.add_initiator.eo.txt --- a/locale/help/initiative.add_initiator.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Inviti inicionton = - -Ĉi tie vi povas inviti personon de via kontaklisto al samrajta kunlaboro pri via skizo. La invitito devas unue akcepti la inviton, antaŭ ol li estas plua iniciinto (kaj estas listigita). **Atentu:** Ĉiuj iniciintoj havas la samajn rajtojn kaj povas forviŝi aliajn iniciintojn. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.add_initiator.zh-Hans.txt --- a/locale/help/initiative.add_initiator.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 邀请发起者 = - -在此您可邀请一位在您通讯录中的联络人来平权合作草案的编辑。被邀请的成员必须首先接受邀请才会成为(并被列为)发起者。 **注意:** 所有发起者有一样的权利并可移除其他发起者。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.add_initiator.zh-TW.txt --- a/locale/help/initiative.add_initiator.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 邀請發起者 = - -在此您可邀請一位在您通訊錄中的聯絡人來平權合作草案的編輯。被邀請的成員必須首先接受邀請才會成為(並被列為)發起者。 **注意:** 所有發起者有一樣的權利並可移除其他發起者。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.remove_initiator.de.txt --- a/locale/help/initiative.remove_initiator.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Initiator entfernen = - -Du kannst dich oder einen anderen Initiator entfernen, sofern nach dem Entfernen noch mindestens ein Initiator existiert. Um die Initiative insgesamt aufzugeben, wähle bitte ,,Initiative zurückziehen''. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.remove_initiator.el.txt --- a/locale/help/initiative.remove_initiator.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -==Αφαίρεση εισηγητή== -Μπορείτε να αφαιρέσετε τον εαυτό σας ή κάποιον άλλο εισηγητή μόνο εάν θα παραμείνει τουλάχιστον ένας. Για να ανακαλέσετε όλη την πρωτοβουλία, παρακαλώ επιλέξτε <<Ανάκληση πρωτοβουλίας>>. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.remove_initiator.en.txt --- a/locale/help/initiative.remove_initiator.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Remove initiator = - -You can remove yourself or another initiator, as long as after the removal there will be at least one initiator left. In order to abandon the entire initiative as such, please select ,,Revoke initiative''. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.remove_initiator.eo.txt --- a/locale/help/initiative.remove_initiator.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Forigi iniciinton = - -Vi povas forigi vin aŭ alian iniciinton, se post la forigo almenaŭ unu iniciinto ekzistos. Por nuligi la iniciaton entute, bonvolu elekti „nuligi iniciaton“. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.remove_initiator.zh-Hans.txt --- a/locale/help/initiative.remove_initiator.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 移除发起者 = - -只要在移除后仍至少还有一位发起者,您可移除您自己或另一位发起者。若要停止整个提案,请选择「撤销提案」。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.remove_initiator.zh-TW.txt --- a/locale/help/initiative.remove_initiator.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 移除發起者 = - -只要在移除後仍至少還有一位發起者,您可移除您自己或另一位發起者。若要停止整個提案,請選擇「撤銷提案」。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.revoke.de.txt --- a/locale/help/initiative.revoke.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Initiative zurückziehen = - -Du kannst diese Initiative zurückziehen. Dies kann nicht rückgängig gemacht werden. Natürlich hast du jederzeit die Möglichkeit, eine neue Initiative zu starten. Den Unterstützern kannst du eine alternative Initiative empfehlen. Angeboten werden dir hierfür alle von dir unterstützten Initiativen. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.revoke.el.txt --- a/locale/help/initiative.revoke.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -==Ανάκληση πρωτοβουλίας== -Μπορείτε να ανακαλέσετε αυτή την πρωτοβουλία. Αυτή η ανάκληση δεν είναι αναστρέψιμη, αλλά μπορείτε πάντα να ξεκινήσετε μία νέα πρωτοβουλία. - -Σας δίνεται η δυνατότητα να προτείνετε στους υποστηρικτές μία εναλλακτική πρωτοβουλία, από αυτές που εσείς υποστηρίζετε. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.revoke.en.txt --- a/locale/help/initiative.revoke.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= Revoke initiative = - -You can revoke this initiative. This cannot be rolled back, but you can, of course, start a new initiative anytime. You can recommend the supporters an alternative initiative. For doing so you are offered all initiatives supported by you. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.revoke.eo.txt --- a/locale/help/initiative.revoke.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -= Nuligi iniciaton = - -Vi povas nuligi iniciaton. Tio estas nemaligebla. Kompreneble, vi havas ĉiumomente la eblecon komenci novan iniciaton. Vi povas rekomendi alternativan iniciaton al la subtenintoj. Por tio vi povas elekti el ĉiuj viaj subtenataj iniciatoj. - diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.revoke.zh-Hans.txt --- a/locale/help/initiative.revoke.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 撤销提案 = - -您可撤销此提案。此动作不可复原,但您当然可在任何时间发起另一个新提案。您可向提案支持者推荐另一个提案。您可自所有所支持的提案中选择要推荐的提案。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.revoke.zh-TW.txt --- a/locale/help/initiative.revoke.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -= 撤銷提案 = - -您可撤銷此提案。此動作不可復原,但您當然可在任何時間發起另一個新提案。您可向提案支持者推薦另一個提案。您可自所有所支持的提案中選擇要推薦的提案。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.show.de.txt --- a/locale/help/initiative.show.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -=Initiative, Unterstützung, Anregungen= -Während der Diskussionsphase kannst du diese Initiative unterstützen und gibst damit den Initiatoren eine wichtige Rückmeldung, inwieweit der aktuelle Entwurf auf Zustimmung stößt. Darüber hinaus kannst du durch Anregungen (Änderungsvorschläge) mitteilen, was noch verbessert werden kann bzw. unter welchen Bedingungen du dir eine Unterstützung vorstellen kannst. - -Du kannst dich den Anregungen anderer Mitglieder anschließen (und damit das Gewicht dieser Anregungen erhöhen) und eigene (zusätzliche) Anregungen einbringen. Anregungen, die aus deiner Sicht unbedingt eingearbeitet werden müssen, damit du zustimmst, kennzeichnest du mit ,,muss'', wünschenswerte mit ,,soll''. Du kannst Anregungen auch kritisch gegenüber stehen und sie mit ,,soll nicht'' kennzeichnen. Eine Anregung, die bei Umsetzung zum Entzug deiner Zustimmung führen würde, kennzeichnest du mit ,,darf nicht''. -=überarbeiteter Entwurf, Umsetzungsvermerk= -Anhand der (klassifizierten und quantifizierten) Anregungen entscheiden die Initiatoren, was sie in einem neuen Entwurf besser darstellen, ergänzen oder ändern. Der geänderte Entwurf wird den Unterstützern zur Bestätigung vorgelegt. Unterstützer können Anregungen als umgesetzt markieren, wenn die Anregung aus ihrer Sicht (hinreichend) umgesetzt wurde. Die einzelnen Unterstützer können diese Frage durchaus unterschiedlich beurteilen. -=weitere Initiatoren einladen, Zurückziehen einer Initiative= -Ein Initiator kann weitere Initiatoren einladen und verleiht ihnen damit gleiche Rechte für die Bearbeitung des Entwurfs. Jeder Initiator einer Initiative kann die Initiative zurückziehen und auf Wunsch den Unterstützern eine andere Initiative als Alternative empfehlen. -=wenn du nicht gehört wirst= -Wenn die Initiatoren deine Anregungen aus für dich nicht nachvollziehbaren Gründen nicht berücksichtigen, kannst du natürlich jederzeit eine eigene Initiative starten. -=wenn du diese Initiative ablehnst= -Wenn du diese Initiative grundsätzlich ablehnst, solltest du auf dieser Seite gar nichts machen, sondern die Initiative(n), der/denen du positiv gegenüber stehst, unterstützen und/oder deine eigene Initiative zu diesem Thema starten. Sofern du nicht ohnehin schon Mitglied des Themenbereichs bist, kannst du durch eine Mitgliedschaft im Themenbereich oder durch Anmeldung von Interesse am Thema die den erforderlichen Unterstützerquorum zugrundeliegende Grundgesamtheit erhöhen. Den gleichen Effekt erreichst du auch, wenn du an ein Mitglied des Themenbereichs oder einen Interessenten am Thema delegierst. **Nur bei Status ,,Neu'':** Falls das Thema, zu dem diese Initiative gehört, noch im Zustand ,,Neu'' ist und du dieses Thema eigentlich gar nicht diskutieren möchtest, solltest du zunächst nur Mitglied des Themenbereichs werden oder Interesse am Thema anmelden und keine Anregungen eingeben, die dich zum (potentiellen) Unterstützer machen würden. Ebenso solltest du noch keine Gegeninitiative starten, die das Thema über die Zulassungshürde heben könnte. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.show.el.txt --- a/locale/help/initiative.show.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -==Πρωτοβουλία== -Κάθε πρωτοβουλία έχει ως στόχο της την αντιμετώπιση και το κλείσιμο του θέματος στο οποίο αναφέρεται. Για να το πετύχουν αυτό, οι εισηγητές τους, παρέχουν μία ολοκληρωμένη πρόταση μέσω του <<προσχεδίου>> της πρωτοβουλίας και τις αναθεωρήσεις του, ζητούν την υποστήριξη του εκλογικού σώματος και λαμβάνουν υπόψη τους τις προτάσεις που τους γίνονται για την βελτίωση του <<προσχεδίου>>. - -=Υποστήριξη και προτάσεις= -Κατά το στάδιο της συζήτησης μπορείτε να υποστηρίξετε αυτήν την πρωτοβουλία και να κάνετε γνωστό, στους εισηγητές, το επίπεδο συμφωνίας σας με το τρέχον <<προσχέδιο>>. Μπορείτε επίσης να κάνετε συγκεκριμένες προτάσεις για βελτιωτικές αλλαγές ή να υποδείξετε τους όρους και τις συνθήκες υπό τις οποίες θα μπορούσατε να υποστηρίξετε την πρωτοβουλία. - -Μπορείτε να ακολουθήσετε τις προτάσεις των άλλων μελών (αυξάνοντας έτσι το βάρος αυτών των προτάσεων) και να καταθέσετε δικές σας (επιπρόσθετες) προτάσεις. Μαρκάρετε τις προτάσεις που θεωρείτε πως είναι απαραίτητες από την πλευρά σας για να εγκρίνετε την πρωτοβουλία με <<οπωσδήποτε>> κι αυτές που θα ήταν καλό να υλοποιηθούν ως <<καλό θα ήταν>>. Μαρκάρετε τις προτάσεις που είστε δύσπιστοι ως <<καλύτερα όχι>> ενώ αυτές που, εάν ενσωματωθούν, θα σας οδηγήσουν να αποδοκιμάσετε την πρωτοβουλία με <<με τίποτα>>. - -=Αναθεωρημένο προσχέδιο και επανέγκριση= -Με βάση τις προτάσεις και την υποστήριξη που συγκεντρώνουν, οι εισηγητές της πρωτοβουλίας αποφασίζουν τι πρέπει να παρουσιάσουν καλύτερα, τι να προσθέσουν ή τι να αλλάξουν στο προσχέδιο ώστε να τύχει ευρύτερης αποδοχής. -Το βελτιωμένο προσχέδιο θα υποβληθεί στους υποστηρικτές της πρωτοβουλίας για επιβεβαίωση. Στη φάση αυτή θα πρέπει να χαρακτηρίσετε τις προτάσεις ως υλοποιημένες ή μη, ανάλογα με το πως κρίνεται το νέο προσχέδιο. Κάθε υποστηρικτής μπορεί να κρίνει τις αλλαγές διαφορετικά. - -=Πρόσκληση επιπλέον εισηγητών, ανάκληση πρωτοβουλίας= -Οι εισηγητές μπορούν να προσκαλέσουν επιπλέον εισηγητές, δίνοντάς τους έτσι ίσα δικαιώματα στην πρωτοβουλία και στην συγγραφή του προσχεδίου. Κάθε εισηγητής μπορεί να ανακαλέσει την πρωτοβουλία, προτείνοντας στους υποστηρικτές της μία εναλλακτική. - -=Εάν δεν εισακουστείτε= -Αν οι εισηγητές, για ανεξήγητους λόγους, δεν λάβουν υπόψη την πρότασή σας, μπορείτε, ασφαλώς, να ξεκινήσετε τη δική σας πρωτοβουλία ανά πάσα στιγμή. - -=Εάν αποδοκιμάζετε αυτή την πρωτοβουλία= -Εάν διαφωνείτε επί της αρχής με αυτή την πρωτοβουλία, δεν πρέπει να κάνετε απολύτως τίποτα σε αυτή την σελίδα. Αντιθέτως, υποστηρίξτε πρωτοβουλίες που βλέπετε θετικά ή/και ξεκινήστε τη δική σας πρωτοβουλία για αυτό το θέμα. - -Αν δεν είστε ήδη μέλος αυτού το τομέα, μπορείτε να αυξήσετε το πλήθος των απαραίτητων υποστηρικτών με το να γίνετε μέλος του τομέα ή με το να δηλώσετε ενδιαφέρον για αυτό το θέμα. Μπορείτε να επιτύχετε το ίδιο με το να αναθέσετε το θέμα σε κάποιο μέλος που ήδη ενδιαφέρεται για το θέμα ή είναι μέλος του τομέα. - -**//Μόνο για το στάδιο <<Νέο>>://** Αν το θέμα αυτής της πρωτοβουλίας είναι ακόμη στο στάδιο <<Νέο>> και, πράγματι, δεν θέλετε ούτε να το συζητήσετε, θα έπρεπε πρώτα να γίνετε μέλος του τομέα ή να δηλώσετε το ενδιαφέρον σας για το θέμα αλλά να μην κάνετε καθόλου προτάσεις, οι οποίες θα σας χαρακτήριζαν (δυνητικό) υποστηρικτή. Επίσης, καλύτερα να μην ξεκινήσετε ακόμη (αντιμέτωπη) εναλλακτική πρωτοβουλία, γιατί θα μπορούσε να βοηθήσει το θέμα να ξεπεράσει το ελάχιστο όριο αποδοχής. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.show.en.txt --- a/locale/help/initiative.show.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -=Initiative, support, suggestion= -During the discussion phase you can support this initiative giving the initiators important feed-back about the approval level of the current draft. Apart from that you can communicate via suggestions (for making changes), what can still be improved, or indicate conditions under which you can imagine to give your support. - -You can follow suggestions of other members (thereby increasing the weight of these suggestions) and come up with your own (additional) suggestions. You can mark suggestions that you believe to be mandatory changes from your point of view, for you to approve with ,,must'', and nice-to-have ones with ,,should''. You can also be skeptical of suggestions and mark them with ,,should not''. You can mark a suggestion that, if realized, would lead you to disapprove, with ,,must not''. -=revised draft, realization notes= -Based on the (classified and quantified) suggestions the initiators decide what to present better, add or change in a new draft. The improved draft will be submitted to the supporters to ask for confirmation. Supporters can mark suggestions as implemented, if from their point of view the suggestions has been (sufficiently) implemented. Individual supporters can judge this quite differently. -=invite further initiators, revoke an initiative= -An initiator can invite further initiators thereby granting them equal rights on editing the draft. Every initiator of an initiative can revoke the initiative and recommend another alternative initiative to the supporters on request. -=if you don't get heard= -If the initiators, for inexplicable reasons, do not consider your suggestion, you can, of course, start your own initiative anytime. -=if you disapprove this initiative= -If you disapprove this initiative fundamentally, you should do nothing at all on this page, but support the initiative(s), that you are positive about, and/or start your own initiative related to this issue. If you are not already a member of the area you can increase the population of the necessary support quorum by becoming a member of the area or by adding your interest to the issue. You can achieve the same effect by delegating to a member of the area or a member interested at the issue. **Only for state ,,New'':** If the issue of this initiative is still in the state ,,New'' and, in fact, you do not want to discuss this issue at all, you should first only become a member of the area or add interest to the issue, but not give any suggestions, making you a (potential) supporter. Also, you should not yet start a counter initiative, which might raise the issue above the minimum admission level. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.show.eo.txt --- a/locale/help/initiative.show.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -=Iniciato, subteno, sugestoj= -Dum la diskutfazo vi povas subteni tiun ĉi iniciaton kaj donas per tio al la iniciintoj gravajn prijuĝajn rimarkojn, kiom da subteno la aktuala skizo ricevas. Plue vi povas komuniki per sugestoj (plibonigaj sugestoj) tion, kio povas esti plibonigota respektive laŭ kiuj kondiĉoj vi povas pripensi subtenon. - -Vi povas aliĝi al la sugestoj de aliaj membroj (kaj pligrandigi la signifon de tiuj ĉi sugestoj) kaj sugesti (pliajn) proprajn ideojn. Sugestojn, kiuj laŭ via vidpunkto nepre devas esti realigotaj, por ke vi konsentu, vi signas per „devas“, dezirindajn per „devus“. Vi ankaŭ povas kritike kontraŭstari sugestojn kaj signi ilin per „ne devus“. Sugestojn, kies realigo kaŭzus la revokon de via konsento, vi signas per „ne rajtas“. -=Prilaborita skizo, realigrimarko= -Laŭ la (klasifikitaj kaj kvantumitaj) sugestoj, la iniciintoj decidas, kion en nova skizo ili prezentas pli bone, aldonas aŭ ŝanĝas. Oni antaŭmetas la ŝanĝitan skizon al la subtenantoj por aprobi. Subtenantoj povas signi sugestojn kiel realigitajn, se la sugestoj laŭ ilia vidpunkto (sufiĉe) realiĝis. La individuaj subtenantoj povas juĝi tiun demandon tute diference. -=Inviti pliajn iniciontojn, nuligi iniciaton= -Iniciinto povas inviti pliajn iniciontojn kaj donas per tio al ili samajn rajtojn por la prilaboro de la skizo. Ĉiu iniciinto povas nuligi la iniciaton kaj laŭdezire rekomendi alian iniciaton al la subtenintoj. -=Se vi ne estas aŭdita= -Se la iniciintoj ne konsideras viajn sugestojn laŭ por vi neakcepteblaj kialoj, vi povas memkompreneble ĉiumomente komenci propran iniciaton. -=Se vi malkonsentas kun tiu ĉi iniciato= -Se vi entute malkonsentas kun tiu ĉi iniciato, vi faru nenion en tiu ĉi paĝo, sed subtenu iniciato(j)n, kun kiu(j) vi konsentas, aŭ komencu propran iniciaton pri tiu ĉi temo. Se vi ne sen tio jam estas membro de la temaro, vi povas pligrandigi la taksobazon de la atingebla kvorumo de subtenantoj per membreco en la temaro aŭ per anonco de intereso pri la temo. Vi atingas la saman efekton, se vi delegas al membro de la temaro aŭ al interesato pri la temo. **Nur ĉe stato „nova“:** Se la temo, al kiu apartenas la iniciato, ankoraŭ estas en la stato „nova“ kaj vi efektive ne ŝatus diskuti la temon, vi unue nur membriĝu ĉe la temaro aŭ anoncu intereson kaj ne enmetu sugestojn, kiuj farus vin (ebla) subtenanto. Same vi ne komencu kontraŭiniciaton, kiu povus puŝi la temon trans la kvorumon. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.show.zh-Hans.txt --- a/locale/help/initiative.show.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -=提案、支持、建议= -在讨论期您可藉由提供发起者关于您对提案接受程度的重要回馈来支持提案。除了建议可改进处,您可指出您可能给予此提案支持的特定条件。 - -您可遵循其他成员的建议(并增加这些建议的份量),并加入您自己额外的建议。在您观点中,您相信是为必须的改变,可标示为「必须」;您相信是为好的建议,可标示为「应当」;您有所质疑的建议,可标示为「不应」;您在理解后所不赞同的建议,可标示为「不可」。 -=已修改草案、更新注记= -根据(已分类并量化的)建议,发起者决定发表更好的、新增或更改一份新的草案。改进过的草案将被送给支持者以请求确认。若支持者认为这些建议已经被充分地采纳,他们可将这些建议标示为被采纳。个别支持者对此的判断可能有极大差异。 -=邀请更多发起者、撤销提案= -发起者可邀请更多发起者,给予他们同等的权限来编辑草案。每个发起者可撤销此提案并应要求推荐另一个替代的提案给支持者。 -=若您的意见未被采纳= -若发起者不知原因地不考虑您的建议,您当然可在任何时候发起您自己的提案。 -=若您不赞同此提案= -若您根本不赞同此提案,请勿在此页面做任何动作。请去支持您所肯定的提案,并/或发起您自己与此议题相关的提案。若您并非此领域的成员,您可成为此领域的成员或关心此议题以提高此提案的必备支持门槛。你可委任给一个领域成员或一个关心此议题的成员以达到同样效果。 **只在「递交期」的状态:** 若此提案的议题仍在「递交期」的状态,并且您实际上一点也不想讨论此议题,您应先成员此领域成员或关心此议题,但不给予任何建议,而成为一个(可能的)支持者。再者,您不应发起一个相对的提案,因为如此可能将此议题提升过最低递交层级。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/initiative.show.zh-TW.txt --- a/locale/help/initiative.show.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -=提案、支持、建議= -在討論期您可藉由提供發起者關於您對提案接受程度的重要回饋來支持提案。除了建議可改進處,您可指出您可能給予此提案支持的特定條件。 - -您可遵循其他成員的建議(並增加這些建議的份量),並加入您自己額外的建議。在您觀點中,您相信是為必須的改變,可標示為「必須」;您相信是為好的建議,可標示為「應當」;您有所質疑的建議,可標示為「不應」;您在理解後所不贊同的建議,可標示為「不可」。 -=已修改草案、更新註記= -根據(已分類並量化的)建議,發起者決定發表更好的、新增或更改一份新的草案。改進過的草案將被送給支持者以請求確認。若支持者認為這些建議已經被充分地採納,他們可將這些建議標示為被採納。個別支持者對此的判斷可能有極大差異。 -=邀請更多發起者、撤銷提案= -發起者可邀請更多發起者,給予他們同等的權限來編輯草案。每個發起者可撤銷此提案並應要求推薦另一個替代的提案給支持者。 -=若您的意見未被採納= -若發起者不知原因地不考慮您的建議,您當然可在任何時候發起您自己的提案。 -=若您不贊同此提案= -若您根本不贊同此提案,請勿在此頁面做任何動作。請去支持您所肯定的提案,並/或發起您自己與此議題相關的提案。若您並非此領域的成員,您可成為此領域的成員或關心此議題以提高此提案的必備支持門檻。你可委任給一個領域成員或一個關心此議題的成員以達到同樣效果。**只在「遞交期」的狀態:** 若此提案的議題仍在「遞交期」的狀態,並且您實際上一點也不想討論此議題,您應先成員此領域成員或關心此議題,但不給予任何建議,而成為一個(可能的)支持者。再者,您不應發起一個相對的提案,因為如此可能將此議題提升過最低遞交層級。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/issue.show.de.txt --- a/locale/help/issue.show.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -= Thema = - -Auf dieser Seite werden alle Initiativen zu diesem Thema aufgelistet. Durch Klicken auf ,,Mein Interesse anmelden'' wird man für dieses Thema den Teilnehmern des übergeordneten Themenbereichs gleichgestellt, wodurch man zur Grundgesamtheit der Diskussionsteilnehmer gezählt wird, was sich auf das von Initiativen zu erreichende Unterstützerquorum auswirkt. - -Angemeldetes Interesse am Thema ist Voraussetzung dafür, dass eine Initiative des Themas direkt unterstützt wird, oder eigene Anregungen gegeben werden. Bei angemeldetem Interesse kommen ausgehende Delegationen für dieses Thema bis zum Abschluss der Phase ,,Eingefroren'' nicht zum tragen. Sobald man eine Initiative des Themas (direkt, nicht durch Delegation) unterstützt, wird das Interesse automatisch angemeldet. Das Zurückziehen des angemeldeten Interesses, entzieht auch die direkten Unterstützerstimmen für Initiativen dieses Themas und aktiviert ggf. ausgesetzte Delegationen. - -Themen durchlaufen die Phasen ,,Neu'', ,,Diskussion'', ,,Eingefroren'', ,,Abstimmung'' und ,,Abgeschlossen'', außer sie gehen bei mangelnden Unterstützerzahlen in den Zustand ,,Abgebrochen'' über. - -Während der Phasen ,,Neu'' und ,,Diskussion'' sollte man **allen** Initiativen, die man grundsätzlich (oder unter bestimmten Bedingungen) für zustimmungsfähig hält, unterstützen und Anregungen zur Verbesserung geben (Näheres dazu findest du auf der Initiativenseite). Hierdurch gibt man den Initiatoren die Chance, den Entwurf zu verbessern. Während dieser Phase hast man auch die Möglichkeit, eine eigene (konkurrierende) Initiative zu diesem Thema zu starten und um Unterstützung zu ringen. - -Initiativen des Themas, die ein bestimmtes Quorum erreichen, werden in die Endabstimmung übernommen. Die Unterstützung für eine Initiative während der Phasen ,,Neu'', ,,Diskussion'' und ,,Eingefroren'' bedeutet keine Festlegung auf das Verhalten in der Endabstimmung. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/issue.show.el.txt --- a/locale/help/issue.show.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -==Θέμα== -Κάθε θέμα έχει μία ή παραπάνω <<πρωτοβουλίες>> τις οποίες καλείστε να υποστηρίξετε, να βελτιώσετε με τις προτάσεις σας και να ψηφίσετε. - -Δηλώνοντας το ενδιαφέρον σας για το θέμα αυξάνετε την βάση αξιολόγησης για την επίτευξη απαρτίας που απαιτείται για κάθε πρωτοβουλία. Το ενδιαφέρον σας για το θέμα θα δηλωθεί αυτόματα εάν υποστηρίξετε μια πρωτοβουλία για αυτό, αλλά δεν θα αφαιρεθεί παρά μόνο αν το επιλέξετε ρητά. - -=Ανάθεση= -Μπορείτε να αναθέσετε το θέμα σε κάποιο άλλο μέλος από τις επαφές σας. Ανάθεση για το θέμα αυτό υπερισχύει πιθανής ανάθεσης για ολόκληρο τομέα ή ενότητα. Επίσης, πιθανή εντολή αυτόματης απόρριψης ισχύει μόνο στην περίπτωση που δεν συμμετάσχετε ο ίδιος στο τελικό στάδιο ψηφοφορίας και δεν γίνει εφαρμογή της ανάθεσης. - -Εάν έχετε δηλώσει ενδιαφέρον για το θέμα, πιθανή εξερχόμενη ανάθεση σας θα ανασταλεί κατά τη διάρκεια του σταδίου συζήτησης αλλά θα είναι ενεργή κατά στην τελική ψηφοφορία. - -=Συζήτηση= -Κατά το στάδιο συζήτησης (κατάσταση <<Νέο>> και <<Συζήτηση>>) είναι σημαντικό **να υποστηρίξετε όλες τις πρωτοβουλίες** οι οποίες σας βρίσκουν γενικά σύμφωνους (ή υπό ορισμένες προϋποθέσεις) και να κάνετε προτάσεις για βελτιώσεις. Μ' αυτό τον τρόπο δίνετε στους εισηγητές την ευκαιρία να βελτιώσουν το προσχέδιο συμπεριλαμβάνοντας τις προτάσεις σας. - -Σε αυτή τη φάση σας δίνεται επίσης η δυνατότητα να ξεκινήσετε την δική σας (ανταγωνιστική) πρωτοβουλία για το θέμα και να ζητήσετε από τα μέλη να την υποστηρίξουν. - -=Ψηφοφορία= -Θέματα που συμπληρώνουν την ορισμένη (από τον ισχύοντα κανονισμό) απαρτία, πηγαίνουν στο στάδιο της ψηφοφορίας. Εκεί μπορείτε να βάλετε τις πρωτοβουλίες που εγκρίνετε σε σειρά προτίμησης, ενώ για άλλες μπορείτε να απέχετε. Τέλος, μπορείτε να βάλετε με σειρά προτίμησης κι αυτές με τις οποίες διαφωνείτε. - -**//Σημαντικό//:** Δεν υπάρχει λόγος να προτιμήσετε μια πρόταση που θεωρείτε κατώτερη άλλης, φοβούμενοι ότι θα <<χαθεί>> η ψήφος σας εξαιτίας προβλεπόμενης πλειοψηφίας μιας άλλης. Για να το θέσουμε απλά, το σύστημα ψηφοφορίας λαμβάνει πλήρως υπόψη του τις προτιμήσεις σας ώστε όταν η πρώτη σας προτίμηση δεν έχει πιθανότητες, η ψήφος σας μετριέται εξ' ολοκλήρου προς την πρώτη σας εναλλακτική, μετά στην δεύτερη, κ.ο.κ. - -Για πληροφορίες σχετικά με την εκλογική διαδικασία που χρησιμοποιείται δείτε: [https://en.wikipedia.org/wiki/Schulze_method] diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/issue.show.en.txt --- a/locale/help/issue.show.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -= Issue = - -This page lists all initiatives belonging to this issue. If you click on ""Add my interest"", you will be treated as equal to the members of the superior areas of this issue, which means that you count for the basic population for discussion in this issue. This has an impact on the supporter quorum, which initiatives have to reach. - -Declared interest is required to be able to directly support initiatives in this issue or to propose suggestions. As long as you are marked as interested in this issue, your outgoing delegations are postponed until the phases ""new"", ""discussion"" and ""frozen"" are finished and the issue is in voting. As soon as you support an initiative of this issue, your interest will be automatically added. Removing your interest also removes all direct support for initiatives of this issues and re-activates a previously postponed delegation. - -Issues run through the phases ""new"", ""discussion"", ""frozen"", ""voting"", and ""finished"", except when they are canceled beforehand due to lack of supporters of initiatives. - -During the phases ""new"" and ""discussion"" you should support **all** initiatives that you can agree with generally (or under certain conditions), and make suggestions for improvements (you can find details on the initiative page). Hereby you give the initiators the chance to improve the draft. During this phase you can also start your own (competing) initiative for this issue and ask people to support it. - -Initiatives reaching a certain quorum, will be taken into the final voting. Support of an initiative during the phases ""new"", ""discussion"" and ""frozen"" does not imply the same decision during final voting. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/issue.show.zh-Hans.txt --- a/locale/help/issue.show.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -= 议题 = - -此页面列出所有属于此议题的提案。若您点击「关心此议题」,您将被与其他此议题上层领域的其他成员同等对待,代表您被计入讨论此议题的基本人数。这将影响提案所需达到的支持者门槛。 - -您必须先关心此议题才可直接支持此议题中的提案或提出建议。只要您关心此议题,您所送出的委任将延后至「递交期」、「讨论期」、「底定期」都结束而此议题已开始表决之时。只要您支持此议题中的一个提案,您将自动关心此议题。移除对此议题的关心也将移除对此议题所有提案的直接支持,并重新启用之前所送出的委任。 - -议题会经历下列阶段:「递交期」、「讨论期」、「底定期」、「表决期」以及「已结束」,除非他们因为提案缺乏支持者而提早被取消。 - -在「递交期」及「讨论期」您应支持**所有**您大致上同意的提案(您可在提案页面上找到细节)。借此您给发起者机会去改进草案。在这时期您也可为此议题发起您自己(相竞争的)提案并请人们去支持。 - -达特定门槛的提案将被列入最终表决。在「递交期」、「讨论期」及「底定期」支持一个提案不代表在最终表决时持相同决定。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/issue.show.zh-TW.txt --- a/locale/help/issue.show.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -= 議題 = - -此頁面列出所有屬於此議題的提案。若您點擊「關心此議題」,您將被與其他此議題上層領域的其他成員同等對待,代表您被計入討論此議題的基本人數。這將影響提案所需達到的支持者門檻。 - -您必須先關心此議題才可直接支持此議題中的提案或提出建議。只要您關心此議題,您所送出的委任將延後至「遞交期」、「討論期」、「底定期」都結束而此議題已開始表決之時。只要您支持此議題中的一個提案,您將自動關心此議題。移除對此議題的關心也將移除對此議題所有提案的直接支持,並重新啓用之前所送出的委任。 - -議題會經歷下列階段:「遞交期」、「討論期」、「底定期」、「表決期」以及「已結束」,除非他們因為提案缺乏支持者而提早被取消。 - -在「遞交期」及「討論期」您應支持**所有**您大致上同意的提案(您可在提案頁面上找到細節)。 藉此您給發起者機會去改進草案。在這時期您也可為此議題發起您自己(相競爭的)提案並請人們去支持。 - -達特定門檻的提案將被列入最終表決。在「遞交期」、「討論期」及「底定期」支持一個提案不代表在最終表決時持相同決定。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit.de.txt --- a/locale/help/member.edit.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Profil = - -Alle Angaben sind freiwillig. Im Profil erscheinen nur die Felder, die nicht leer sind. - -Screen-Name, Anmeldename sowie das Kennwort lassen sich im Benutzermenü unter Einstellungen ändern. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit.el.txt --- a/locale/help/member.edit.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -=Προφίλ= -Όλες οι πληροφορίες συμπληρώνονται εθελοντικά. Μόνο μη κενά πεδία θα εμφανίζονται στο προφίλ σας. - -Για να αλλάξετε το ψευδώνυμο, το όνομα σύνδεσης ή τον κωδικό πρόσβασής σας πηγαίνετε στη σελίδα 'Επιλογές' από το μενού χρήστη πάνω δεξιά. Για να αλλάξετε την φωτογραφία και την εικόνα σας επιλέξτε 'Ανέβασμα εικόνων'. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit.en.txt --- a/locale/help/member.edit.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Profile = - -All information entered here is voluntary. Only non-empty fields will be shown in your profile. - -You can change your name, login name and password in your user menu at the upper right corner under ""settings"". diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit.eo.txt --- a/locale/help/member.edit.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= Profilo = - -Ĉiuj deklaroj estas libervolaj. En via profilo nur tiuj kampoj, kiuj ne estas malplenaj, estas videblaj. - -You can change your name, login name and password in your user menu at the upper right corner under ""settings"". diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit.zh-Hans.txt --- a/locale/help/member.edit.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 个人简介 = - -所有在此的资讯都是自愿输入的。只有非空白内容会被显示在您的个人简介。 - -您可在右上角「设定」的使用者选单中改变您的使用者代号、帐号以及密码。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit.zh-TW.txt --- a/locale/help/member.edit.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -= 個人簡介 = - -所有在此的資訊都是自願輸入的。只有非空白內容會被顯示在您的個人簡介。 - -您可在右上角「設定」的使用者選單中改變您的使用者代號、帳號以及密碼。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit_images.de.txt --- a/locale/help/member.edit_images.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -= Bilder = - -Format: JPG -Avatar: max. 48 x 48 Pixel, für den Avatar bevorzugt ein quadratisches Bild -Foto: max. 250 x 250 Pixel -Größere Bilder werden herunterskaliert, alle Bilder werden recodiert und von Profilen befreit. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit_images.el.txt --- a/locale/help/member.edit_images.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -=Εικόνες= -Μορφή: JPG -Εικόνα (Avatar): μεγ. 48 x 48 pixels, μια τετράγωνη εικόνα κατά προτίμηση. -Φωτογραφία: μεγ. 250 x 250 pixels - -Μεγαλύτερες εικόνες θα σμικρυνθούν. Όλες οι εικόνες θα επανακωδικοποιηθούν και τα δεδομένα προφίλ τους θα αφαιρεθούν. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit_images.en.txt --- a/locale/help/member.edit_images.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -= Images = - -Format: JPG -Avatar: max. 48 x 48 pixels, an image in square format is preferred for your avatar -Picture: max. 250 x 250 pixels -Larger images will be scaled down, all images will be recoded and profile data be removed. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit_images.eo.txt --- a/locale/help/member.edit_images.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -= Bildoj = - -Formato: JPG -Avataro: maksimume 48 × 48 rastrumeroj, por la avataro prefereble kvadrata bildo -Foto: maksimume 250 × 250 rastrumeroj -Pli grandaj bildoj reduktiĝas; ĉiuj bildoj rekodiĝas kaj liberiĝas de profiloj. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit_images.zh-Hans.txt --- a/locale/help/member.edit_images.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -= 图片 = - -格式:JPG -头像:最大 48 x 48 画素,一张横式的图片较适合做为您的头像。 -照片: 最大 250 x 250 画素 -更大的图片会被缩小,所有的图片将被重新编码,而图片附属资讯将被去除。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.edit_images.zh-TW.txt --- a/locale/help/member.edit_images.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -= 圖片 = - -格式:JPG -頭像:最大 48 x 48 畫素,一張橫式的圖片較適合做為您的頭像。 -照片: 最大 250 x 250 畫素 -更大的圖片會被縮小,所有的圖片將被重新編碼,而圖片附屬資訊將被去除。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.email_address.de.txt --- a/locale/help/member.settings.email_address.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Diese E-Mail-Adresse kann für automatische Nachrichten des Systems sowie für die Kontaktaufnahme durch die Administratoren verwendet werden und wird anderen Benutzern nicht angezeigt. Wenn Du die Adresse änderst, erhältst Du eine E-Mail mit einem Bestätigungslink, den du anklicken musst. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.email_address.el.txt --- a/locale/help/member.settings.email_address.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Αυτή η διεύθυνση email μπορεί να χρησιμοποιηθεί για αυτοματοποιημένα μηνύματα από το σύστημα ή για επικοινωνία από τους διαχειριστές του συστήματος. Δεν εμφανίζεται σε άλλους χρήστες. Αν αλλάξετε αυτή την διεύθυνση θα λάβετε ένα μήνυμα επιβεβαίωσης της νέας διεύθυνσης με έναν σύνδεσμο που πρέπει να ακολουθήσετε. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.email_address.en.txt --- a/locale/help/member.settings.email_address.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -This e-mail address can be used for automatic messages from the system as well as for approach by the administrators of the system. It is not displayed to other users. If you change this address, you receive an e-mail with a verification link, which you have to follow. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.email_address.zh-Hans.txt --- a/locale/help/member.settings.email_address.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -此电邮地址可被系统用来发送自动讯息,或被系统管理员用来联络您。此电邮地址将不公开显示。若您更改此地址,您会收到一封有认证连结的电邮,您必须遵循上面的指示。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.email_address.zh-TW.txt --- a/locale/help/member.settings.email_address.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -此電郵地址可被系統用來發送自動訊息,或被系統管理員用來聯絡您。此電郵地址將不公開顯示。若您更改此地址,您會收到一封有認證連結的電郵,您必須遵循上面的指示。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.login.de.txt --- a/locale/help/member.settings.login.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Bitte wähle einen Anmeldenamen. Dieser wird anderen nicht gezeigt und nur von Dir zum Anmelden verwendet. Groß- und Kleinschreibung wird berücksichtigt. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.login.el.txt --- a/locale/help/member.settings.login.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Παρακαλώ επιλέξτε ένα όνομα σύνδεσης. Αυτό το όνομα δεν θα εμφανίζεται σε άλλους και χρησιμοποιείται μόνο για την σύνδεσή σας στο σύστημα. Προσοχή στα κεφαλαία/πεζά γράμματα, έχουν σημασία. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.login.en.txt --- a/locale/help/member.settings.login.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Please choose a login name. It will not be visible for other users and you will only use it for logging in. The login name is case-sensitive. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.login.eo.txt --- a/locale/help/member.settings.login.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Bonvolu elekti salutnomon. Tiu ne montriĝas al aliaj kaj estas uzata nur de vi por ensaluti. Uskleco estas konsiderata. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.login.zh-Hans.txt --- a/locale/help/member.settings.login.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -请选择一个帐号。此帐号将不会显示给其他使用者,而只由您在登入时使用。帐号的大小写是有区别的。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.login.zh-TW.txt --- a/locale/help/member.settings.login.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -請選擇一個帳號。此帳號將不會顯示給其他使用者,而只由您在登入時使用。帳號的大小寫是有區別的。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.name.de.txt --- a/locale/help/member.settings.name.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Wähle einen Namen, z. B. Deinen Real- oder Nicknamen. Dieser wird anderen angezeigt um Dich zu identifizieren. Aus Gründen der Transparenz können alte Namen in Deiner Namenshistorie im Profil abgerufen werden. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.name.el.txt --- a/locale/help/member.settings.name.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -Παρακαλώ επιλέξτε ένα όνομα, π.χ. το πραγματικό σας ή κάποιο ψευδόνυμο. Το όνομα αυτό θα εμφανίζεται στους άλλους για να σας αναγνωρίζουν. - -Για λόγους διαφάνειας, το ιστορικό του ονόματός σας είναι διαθέσιμο σε άλλους και φαίνεται στη σελίδα του προφίλ σας. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.name.en.txt --- a/locale/help/member.settings.name.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Choose a name, e.g. your real name or a nick name. This name will be visible for other users, in order to identify you. For reasons of transparency the history of your names is available for others looking at your profile. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.name.eo.txt --- a/locale/help/member.settings.name.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Elektu nomon, ekzemple vian veran aŭ kaŝnomon. Tiu montriĝas por identigi vin. Pro kialoj de travideblo malnovaj nomoj montriĝas en la nomhistorio de via profilo. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.name.zh-Hans.txt --- a/locale/help/member.settings.name.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -请选择一个使用者代号,例如您的真名或绰号。此使用者代号将会显示给其他使用者,以便辨​​认您。为了维持透明度,其他使用者可在您的个人简介看到您使用者代号的更改纪录。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.name.zh-TW.txt --- a/locale/help/member.settings.name.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -請選擇一個使用者代號,例如您的真名或綽號。此使用者代號將會顯示給其他使用者,以便辨認您。為了維持透明度,其他使用者可在您的個人簡介看到您使用者代號的更改紀錄。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.notification.de.txt --- a/locale/help/member.settings.notification.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -=Benachrichtigungseinstellungen= -Hier kannst du einstellen, ob du überhaupt und wenn ja welche Benachrichtigungen du vom System per E-Mail erhalten möchtest. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.notification.el.txt --- a/locale/help/member.settings.notification.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Επιλέξτε τα γεγονότα για τα οποία θέλετε να λαμβάνετε ειδοποιήσεις μέσω email. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.notification.en.txt --- a/locale/help/member.settings.notification.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -=Notification settings= -Please choose which notifications you like to receive from the system by email. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.notification.zh-Hans.txt --- a/locale/help/member.settings.notification.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -=通知设定= -请选择您想从系统收到的电邮通知种类。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.notification.zh-TW.txt --- a/locale/help/member.settings.notification.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -=通知設定= -請選擇您想從系統收到的電郵通知種類。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.password.de.txt --- a/locale/help/member.settings.password.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Dein neues Kennwort muss mindestens 8 Zeichen lang sein. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.password.el.txt --- a/locale/help/member.settings.password.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -Ο νέος σας κωδικός πρέπει να έχει τουλάχιστον 8 χαρακτήρες. Δώστε προσοχή στα κεφαλαία/πεζά γράμματα, έχουν σημασία. - -**Προσοχή:** Μη δίνετε ποτέ τον κωδικό πρόσβασής σας σε άλλους, ακόμη κι αν ισχυρίζονται πως είναι διαχειριστές. - diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.password.en.txt --- a/locale/help/member.settings.password.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Your new password must have at least 8 characters. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.password.eo.txt --- a/locale/help/member.settings.password.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Via nova pasvorto devas esti minimume ok signojn longa. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.password.zh-Hans.txt --- a/locale/help/member.settings.password.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -您的新密码必须至少有 8 个符号。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.settings.password.zh-TW.txt --- a/locale/help/member.settings.password.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -您的新密碼必須至少有 8 個符號。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.show.de.txt --- a/locale/help/member.show.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -=Profilseite= -Hier kann man erfahren, -- was dieses Mitglied über sich selbst mitteilt, -- in welchen Themenbereichen es Mitglied ist, -- an welchen Themen und Initiativen es sich beteiligt -- welche Delegationen das Mitglied erhalten und erteilt und -- welche Kontakte das Mitglied veröffentlicht hat. -=zu den Kontakten hinzufügen= -Hier kann man das Mitglied außerdem zur eigenen Kontaktliste hinzufügen (und es natürlich auch wieder von dieser entfernen). Bitte beachte, dass man nur an Mitglieder delegieren kann, die man auf die eigene Kontaktliste gesetzt hat. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.show.el.txt --- a/locale/help/member.show.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -==Σελίδα προφίλ== -Εδώ μπορείτε να δείτε: -- Τι λέει αυτό το μέλος για τον εαυτό του και τα στοιχεία που επέλεξε να μοιραστεί -- Σε ποιες ενότητες, τομείς και θέματα συμμετέχει -- Τις αναθέσεις που έχει ορίσει και έχει δεχτεί -- Τις επαφές του επέλεξε να δημοσιεύσει - -=Προσθήκη στις επαφές σας= -Μπορείτε να αποθηκεύσετε αυτό το μέλος στις επαφές σας (και να το αφαιρέσετε πάλι, βεβαίως). Αυτό είναι απαραίτητο όταν, για παράδειγμα, θέλετε να ορίσετε το μέλος ως αντιπρόσωπό σας, αναθέτοντάς του κάποια <<ενότητα>>, <<τομέα>> ή <<θέμα>>. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.show.en.txt --- a/locale/help/member.show.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -=Profile page= -Here you can learn, -- what this member says about him- or herself, -- which areas he or she is a member of, -- in which issues and initiatives he or she participates -- which delegations the member has received and given, and -- which contacts the member has published. -=add to contacts= -You can add this member to your list of contacts (and also remove him or her from it, again, of course). Please note that you can only delegate to members, who are on your list of contacts. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.show.eo.txt --- a/locale/help/member.show.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -=Profilpaĝo= -Ĉi tie vi povas ekscii, -– kion tiu ĉi membro komunikas pri si mem, -– de kiuj temaroj li estas membro, -– kiujn temojn kaj iniciatojn li partoprenas, -– kiujn delegaciojn la membro ricevas kaj donas kaj -– kiujn kontaktojn la membro publikigis. -=Aldoni al la kontaktoj= -Vi povas aldoni tiun ĉi membron al via kontaktlisto (kaj kompreneble denove forigi lin de ĝi). Bonvolu atenti, ke vi povas delegi nur al membroj, kiuj estas en via kontaktlisto. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.show.zh-Hans.txt --- a/locale/help/member.show.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -=个人简介= -在此您可了解: -- 此成员对个人的描述 -- 他或她是哪些领域的成员 -- 他或她参与哪些议题或提案 -- 此成员所送出或收到的委任 -- 此成员公开的联络人 -=加入通讯录= -您可将此成员加入您的通讯录(当然之后可再移除之)。请注意,您只可委任给在您通讯录中的成员。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/member.show.zh-TW.txt --- a/locale/help/member.show.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -=個人簡介= -在此您可瞭解: -- 此成員對個人的描述 -- 他或她是哪些領域的成員 -- 他或她參與哪些議題或提案 -- 此成員所送出或收到的委任 -- 此成員公開的聯絡人 -=加入通訊錄= -您可將此成員加入您的通訊錄(當然之後可再移除之)。請注意,您只可委任給在您通訊錄中的成員。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/policy.list.de.txt --- a/locale/help/policy.list.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Die folgenden Regelwerke sind zur Zeit konfiguriert. Nicht alle Regelwerke müssen in jedem Themengebiet verfügbar sein. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/policy.list.el.txt --- a/locale/help/policy.list.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -==Κανονισμοί== -Οι κανονισμοί καθορίζουν τη διάρκεια των σταδίων των θεμάτων και τις ποσοτικές παραμέτρους πλειοψηφίας και απαρτίας. Κάθε θέμα υπόκειται σε έναν από τους παρακάτω κανονισμούς. - -//Σημείωση:// Μπορεί κάποιοι κανονισμοί να μην είναι διαθέσιμοι σε όλους τους τομείς και κατ' επέκταση στα θέματα τους. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/policy.list.en.txt --- a/locale/help/policy.list.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -The following policies are currently configured. Not all policies are available in every subject area. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/policy.list.eo.txt --- a/locale/help/policy.list.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -La sekvontaj regularoj estas nuntempe agorditaj. Ne ĉiuj regularoj devas esti atingeblaj ĉe ĉiu temaro. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/policy.list.zh-Hans.txt --- a/locale/help/policy.list.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -下列规则是目前所设定的。并非所有规则在每个主题领域都适用。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/policy.list.zh-TW.txt --- a/locale/help/policy.list.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -下列規則是目前所設定的。並非所有規則在每個主題領域都適用。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/vote.list.de.txt --- a/locale/help/vote.list.de.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -= Abstimmung = - -Zu Beginn der Abstimmung befinden sich alle Initiativen im Feld Enthaltung. Beginne am besten mit deinem Favoriten und ziehe ihn mit der Maus in das Feld Zustimmung. Danach wählst du die nächste Initiative, der du zustimmen möchtest und ziehst sie -- in die gleiche grüne Box, falls du dieser Initiative gleichberechtigt zustimmen möchtest oder -- zwischen die Zustimmungs- und Enthaltungsbox, falls diese Initiative dein Ersatzwunsch sein soll. - -Auf diese Weise fährst du fort und legst die Präferenzreihenfolge der Initiativen, denen du zustimmen möchtest fest, wobei du gleichwertige Initiativen jeweils in die gleiche Box hineinziehst. Dann legst du deine Enthaltungen und Ablehnungen fest, wobei du auch die Ablehnungen in eine Rangreihenfolge bringen kannst, falls eine der Initiativen so etwas wie das ,,kleinere Übel'' darstellen sollte. - -**Wichtig:** Verlasse diese Seite über die Schaltfläche ,,Stimmabgabe abschließen''. Bis zum Ende der Abstimmung kannst du deine Angaben jederzeit ändern. Es werden keine Zwischenergebnisse der Abstimmung veröffentlicht. Die Unterstützerangaben auf der Themenübersichtsseite beziehen sich auf die abgeschlossene Diskussion, beziehen sich jeweils auf die einzelne Initiative und sind nur sehr bedingt geeignet, zwischen den Initiativen zu vergleichen. Insbesondere enthalten sie keinerlei Informationen über Präferenzen. Darüber hinaus kann sich der Teilnehmerkreis von Diskussion und Abstimmung erheblich unterscheiden. - -**Achtung:** Auf einigen Plattformen (zum Beispiel Smartphones oder Tablet-Computern) ist das Ziehen von Initiativen mit der Maus nicht möglich. In diesem Falle können die Pfeile links neben den jeweiligen Initiativen verwendet werden. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/vote.list.el.txt --- a/locale/help/vote.list.el.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -==Ψηφοφορία== -Κατά την έναρξη της ψηφοφορίας όλες οι πρωτοβουλίες θα είναι στο πλαίσιο <<Αποχή>>. Συνιστάται να ξεκινήσετε με την αγαπημένη σας και την σύρετε με το ποντίκι σας στο πλαίσιο <<Επιδοκιμασίας>>. Στη συνέχεια επιλέξτε την επόμενη πρωτοβουλία που θέλετε να εγκρίνετε και σύρετέ την είτε: -- Στο ίδιο πράσινο κουτί, αν θέλετε να την εγκρίνετε εξίσου ή -- Μεταξύ του πλαισίου <<Επιδοκιμασίας>> και <<Αποχής>>, αν θέλετε αυτή η πρωτοβουλία να είναι δεύτερη επιλογή σας. - -Συνεχίζοντας έτσι καθορίζετε τη σειρά προτίμησης των πρωτοβουλιών που θέλετε να εγκρίνετε, δηλαδή σέρνετε ίσης προτίμησης πρωτοβουλίες στο ίδιο κουτί. Στη συνέχεια, καθορίζετε αυτές που απέχετε και αυτές που αποδοκιμάζετε, πράγμα που σημαίνει ότι μπορείτε επίσης να ορίσετε τη σειρά προτίμησης για τις απορρίψεις, για την περίπτωση που μία από τις πρωτοβουλίες αντιπροσωπεύει το "μικρότερο κακό''. - -**Σημαντικό:** Για να φύγετε από αυτή την σελίδα πατήστε το κουμπί <<Ολοκλήρωση ψήφου>>. Μπορείτε να αλλάξετε τις ψήφους σας οποιαδήποτε στιγμή μέχρι το τέλος της ψηφοφορίας. - -=Αποτελέσματα κατά τη διάρκεια της ψηφοφορίας= -Κατά τη διάρκεια της ψηφοφορίας δεν δημοσιεύονται ενδιάμεσα αποτελέσματα. Τα στοιχεία που παρουσιάζονται στη σελίδα επισκόπησης αναφέρονται μόνο στην αντίστοιχη πρωτοβουλία και είναι κατάλληλα μόνο για συγκρίσεις σε περιορισμένο βαθμό. Ειδικότερα, δεν περιέχουν καμία πληροφορία σχετικά με τις προτιμήσεις και επιπλέον η ομάδα των ατόμων που συμμετέχουν στη συζήτηση μπορεί να είναι πολύ διαφορετική από αυτούς που πραγματικά ψηφίζουν. - -//Σημείωση:// Σε ορισμένες πλατφόρμες (π.χ. κινητά τηλέφωνα ή υπολογιστές tablet) μπορεί να μην είναι δυνατό να σύρετε τις πρωτοβουλίες. Σε αυτές τις περιπτώσεις, χρησιμοποιήστε το πάνω και το κάτω βέλος αριστερά της κάθε πρωτοβουλίας. \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/vote.list.en.txt --- a/locale/help/vote.list.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -= Voting = - -At the beginning of the voting all initiatives will be in the Abstention field. It is recommended to start with your favourite and drag it with your mouse into the Approval field. Then you select the next initiative that you want to approve and drag it either -- into the same green box, if you want to approve it equally or -- between the Approval and Abstention box, if you want this initiative to be your second choice. - -Continuing like this you define the preference list of the initiatives, that you want to approve, i.e. you drag equal initiatives into the same box. Then you specify your abstentions and disapprovals, meaning that you can also define a preference list for disapprovals, just in case one of the initiatives should represent something like a ,,minor evil''. - -**Important:** Leave this page via the ,,Finish voting'' button. You can change your votes anytime until the end of the voting. During the voting no interim results are published. The support data on the issue overview page refers to the single respective initiative and is only suited to a very limited extent to compare different initiatives. Especially, it contains no information whatsoever about preferences. Moreover, the group of those participating in the discussion can be very different from those who actually vote. - -**Notice:** On some platforms (e.g. smartphones or tablet computers) "drag and drop" via mouse is not possible. In these cases use the up and down arrows left of each initiative. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/vote.list.eo.txt --- a/locale/help/vote.list.eo.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -=Voĉdono= -Depende, kiujn agordojn vi elektis, ĉiuj iniciatoj troviĝas komence en la kampo „sindeteno“ aŭ en la kampo „malkonsento“. Komencu pli bone kun via favorato kaj tiru ĝin permuse en la kampon „konsento“. Poste vi elektas la sekvan iniciaton, kiun vi volas konsenti kaj tiras ĝin -– en la saman verdan ujon, se vi ŝatus samrajte konsenti kun tiu ĉi iniciato aŭ -– inter la konsento- kaj la sindetenujojn, se tiu ĉi iniciato estu via anstataŭa deziro. - -Tiamaniere, vi daŭrigas kaj decidas la prefervicon de la iniciatoj, kun kiuj vi ŝatus konsenti, ĉe kio vi tiras samrangajn iniciatojn en la saman ujon. Tiam vi decidas la sindetenojn kaj la malkonsentojn, ĉe kio vi povas meti ankaŭ la malkonsentojn en prefervicon, se unu el la iniciatoj ŝajnus „la pli malgranda malbono“. - -**Grave:** Forlasu tiun ĉi paĝon per la butono „fini voĉdonadon“. Ĝis la fino de la voĉdonado vi povas ĉiutempe ŝanĝi viajn deklarojn. Provizoraj rezultoj de la voĉdono ne publikiĝas. La indiko de subtenantoj rilatas al finitaj diskutoj, rilatas al la aparta iniciato kaj nur tre relative taŭgas por kompari inter iniciatoj. Precipe, ili ne enhavas informojn pri preferoj. Krome, la partoprenantaroj de diskuto kaj voĉdono povas konsiderinde malsami. diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/vote.list.zh-Hans.txt --- a/locale/help/vote.list.zh-Hans.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -= 表决 = - -在表决开始时所有提案都放置在弃权区。我们建议您从您最喜爱的提案开始,并以滑鼠将其拖移至赞同区。然后选择下一个您所赞同的提案并将其拖移 -- 若您对两者同样赞同,拖移至同个绿盒子内 -- 若您想将此提案成为第二选择,就拖移至赞同与弃权区间 - - -如此继续,您便指定了您所赞同的提案的偏好列表,也就是您将一样赞同的提案都拖移到同个盒子里。然后您指定您所要弃权或否决的提案,也就是在某个提案对您来说只是个「小恶魔」时,您也指定您所否决的提案的偏好列表。 - -**重要:** 请藉由「完成投票」按钮离开本页面。直到表决结束您都可更改您的投票。在表决期间不会有临时结果被公开。议题概观页面所显示的支持统计资料只针对单一提案,并且对于比较不同的提案只有非常局限的用途。特别是,它并不含有任何关于偏好的资讯。再者,参与讨论的成员组成可能与实际参与表决的成员组成非常不同。 - -**注意:** 在某些平台(例如智慧型手机或平板电脑)以滑鼠拖放是不可能的。在此状况下请使用个案左侧的上下箭头。 \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/vote.list.zh-TW.txt --- a/locale/help/vote.list.zh-TW.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -= 表決 = - -在表決開始時所有提案都放置在棄權區。我們建議您從您最喜愛的提案開始,並以滑鼠將其拖移至贊同區。然後選擇下一個您所贊同的提案並將其拖移 -- 若您對兩者同樣贊同,拖移至同個綠盒子內 -- 若您想將此提案成為第二選擇,就拖移至贊同與棄權區間 - - -如此繼續,您便指定了您所贊同的提案的偏好列表,也就是您將一樣贊同的提案都拖移到同個盒子裡。然後您指定您所要棄權或否決的提案,也就是在某個提案對您來說只是個「小惡魔」時,您也指定您所否決的提案的偏好列表。 - -**重要:** 請藉由「完成投票」按鈕離開本頁面。直到表決結束您都可更改您的投票。在表決期間不會有臨時結果被公開。議題概觀頁面所顯示的支持統計資料只針對單一提案,並且對於比較不同的提案只有非常侷限的用途。特別是,它並不含有任何關於偏好的資訊。再者,參與討論的成員組成可能與實際參與表決的成員組成非常不同。 - -**注意:** 在某些平台(例如智慧型手機或平板電腦)以滑鼠拖放是不可能的。在此狀況下請使用個案左側的上下箭頭。 diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/wikisyntax.en.txt --- a/locale/help/wikisyntax.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -==== Wiki Help ==== - -You can choose between this different syntaxes: - -[wikisyntax_rocketwiki.html RocketWiki] -[wikisyntax_compat.html Traditional wiki syntax] diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/wikisyntax_compat.en.txt --- a/locale/help/wikisyntax_compat.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -<- [wikisyntax.html Wiki Help] - -==== Traditional Wiki-Syntax ==== -- ++Headings++ --- = Main Heading (H1) = --- == Heading (H2) == --- === Sub-Heading (H3) === --- ==== Sub-Sub-Heading (H4) ==== -- ++Horizontal line++ --- --- -- ++Unnumbered lists++ --- * Toplevel Entry --- ** Sub Entry -- ++Numbered list++ --- # Toplevel Entry --- ## Sub Entry -- ++Font style++ --- {{'''bold'''}} --- {{''italic''}} --- {{possible tags: big, small, sup, sub, tt, nobr}} --- {{{{no special interpretation of formatting characters}}}} -- ++Text flow++ --- non-breaking(_)space --- soft(-)hypen -- ++Dashes++ --- En{{{--}}}Dash --- Em{{{---}}}Dash -- ++Line break++ --- {{
}} -- ++Links++ --- {{[http://example.org/ link text]}} diff -r a6c7bf07badb -r 701a5cf6b067 locale/help/wikisyntax_rocketwiki.en.txt --- a/locale/help/wikisyntax_rocketwiki.en.txt Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -<- [wikisyntax.html Wiki Help] - -==== RocketWiki ==== -- ++Headings++ --- ==== Main Heading (H1) ==== --- === Heading (H2) === --- == Sub-Heading (H3) == --- = Sub-Sub-Heading (H4) = -- ++Horizontal line++ --- --- -- ++Unnumbered lists++ --- - Toplevel Entry --- -- Sub Entry -- ++Numbered list++ --- # Toplevel Entry --- ## Sub Entry -- ++Font style++ --- {{**bold**}} --- {{//italic//}} --- {{__underlined__}} --- {{++big++}} --- {{%%small%%}} --- {{||monospaced||}} --- {{&&no line break&&}} --- {{{{no special interpretation of formatting characters}}}} -- ++Quotes++ --- {{""normal english quotes""}} --- {{"""single english quotes"""}} --- {{,,normal german quotes''}} --- {{,,,single german quotes'''}} --- {{<>}} --- {{<<>>}} -- ++Text flow++ --- non-breaking(_)space --- soft(-)hypen -- ++Special characters++ --- {{{EUR}}} sign --- German umlauts: {{{Ae} {Oe} {Ue} {ae} {oe} {ue}}} --- German SZ-ligature: {{{sz} or {ss}}} --- Mid{{{.}}}dot --- Ellipsis {{{...}}} --- Arrows {{{->} {=>} {<->}}} etc. --- {{{C} 2009, Registered{R}, Trademark{TM}}} --- {{360{deg} 0{'} 0{''}}} **=>** 360{deg} 0{'} 0{''} --- {{{1/4} + {1/2} = {3/4}}} **=>** {1/4} + {1/2} = {3/4} --- {{10{%o} = 1%}} **=>** 10{%o} = 1% --- {{(5 {-} 1) {x} 3 {/} 4 {=} 3}} **=>** (5 {-} 1) {x} 3 {/} 4 {=} 3 -- ++Dashes++ --- En{{{--}}}Dash --- Em{{{---}}}Dash -- ++Links++ --- {{[http://example.org/ link text]}} diff -r a6c7bf07badb -r 701a5cf6b067 locale/translations.de.lua --- a/locale/translations.de.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/locale/translations.de.lua Thu Jul 10 01:19:48 2014 +0200 @@ -1,36 +1,61 @@ #!/usr/bin/env lua return { +["#{closed_ago} ago"] = "vor #{closed_ago}"; +["#{count} Neutral"] = "#{count} Enthaltung"; +["#{count} No"] = "#{count} Nein"; +["#{count} Yes, alternative choice"] = "#{count} Ja, Alternativstimme"; +["#{count} Yes, first choice"] = "#{count} Ja, Erststimme"; ["#{count} canceled"] = "#{count} abgebrochen"; -["#{count} days ago"] = "vor #{count} Tagen"; ["#{count} finished"] = "#{count} abgeschlossen"; ["#{count} in discussion"] = "#{count} in Diskussion"; ["#{count} in verification"] = "#{count} eingefroren"; ["#{count} in voting"] = "#{count} in Abstimmung"; -["#{count} more areas in this unit"] = "#{count} weitere Themengebiete in dieser Gliederung"; +["#{count} matching issues found"] = "#{count} passende Themen gefunden"; +["#{count} matching members found"] = "#{count} passende Mitglieder gefunden"; +["#{count} more areas in this unit"] = "#{count} weitere Themenbereiche in dieser Gliederung"; ["#{count} new"] = "#{count} neue"; ["#{count} of them have an area delegation set"] = "bei #{count} davon ist eine Delegation für den Themenbereichs gesetzt"; ["#{count} of your outgoing delegation(s) are broken"] = "#{count} deiner ausgehenden Delegationen sind kaputt"; -["#{date} at #{time}"] = "am #{date} um #{time}"; +["#{count} supporter"] = "#{count} Unterstützer"; +["#{duration}"] = false; ["#{interested_issues_to_vote_count} issue(s) you are interested in"] = "#{interested_issues_to_vote_count} Themen, die Dich interessieren"; ["#{interval_text} [interval]"] = "#{interval_text}"; ["#{interval_text} ago"] = "vor #{interval_text}"; ["#{interval_text} left"] = "noch #{interval_text}"; +["#{interval} ago"] = "vor #{interval}"; ["#{issues_to_vote_count} issue(s)"] = "#{issues_to_vote_count} Themen"; +["#{issue} is in voting"] = "#{issue} ist in Abstimmung"; ["#{name}\n\n"] = "#{name}\n\n"; ["#{number} Image(s) has been deleted"] = "Es wurde(n) #{number} Bild(er) gelöscht"; ["#{number} Image(s) has been updated"] = "Es wurde(n) #{number} Bild(er) aktualisiert"; +["#{percentage}%"] = false; ["#{policy_name} ##{issue_id}"] = false; ["#{policy} ##{id}"] = false; -["(#{more_count} duplicates removed)"] = "(#{more_count} Duplikate entfernt)"; +["#{result}: #{yes_count} Yes (#{yes_percent}), #{no_count} No (#{no_percent}), #{neutral_count} Abstention (#{neutral_percent})"] = "#{result}: #{yes_count} Ja (#{yes_percent}), #{no_count} Nein (#{no_percent}), #{neutral_count} Enthaltung (#{neutral_percent})"; +["#{result}: No votes (0)"] = "#{result}: Keine Stimmen (0)"; +["(+ #{count} potential)"] = "(+ #{count} potentielle)"; +["(1) Admission"] = "(1) Zulassung"; +["(1) Admission phase"] = "(1) Zulassungsphase"; +["(2) Discussion"] = "(2) Diskussion"; +["(2) Discussion phase"] = "(2) Diskussionsphase"; +["(3) Verification"] = "(3) Überprüfung"; +["(3) Verification phase"] = "(3) Überprüfungsphase"; +["(4) Voting"] = "(4) Abstimmung"; +["(4) Voting phase"] = "(4) Abstimmungsphase"; +["(5) Result"] = "(5) Ergebnis"; +["(invited)"] = "(eingeladen)"; ["(new window)"] = "(neues Fenster)"; -[")) == "] = false; ["+ #{weight}"] = "+ #{weight}"; +["+ add new organizational unit"] = "+ neue Gliederung hinzufügen"; +["+ add new subject area"] = "neuen Themenbereich hinzufügen"; ["+getElementById("] = false; +["1 matching issue found"] = "1 passendes Thema gefunden"; +["1 matching member found"] = "1 passendes Mitglied gefunden"; +["4 phases of a decision"] = "4 Phasen einer Entscheidung"; +["A short title (80 chars max)"] = "Ein kurzer Titel (max. 80 Zeichen)"; ["A-Z"] = "A-Z"; -["API Key"] = "API-Key"; ["API key has been created"] = "API-Schlüssel wurde erzeugt"; ["API key has been deleted"] = "API-Schlüssel wurde gelöscht"; -["API keys"] = "API-Schlüssel"; ["Abandon global delegation for this area"] = "Aussetzen der globale Delegation"; ["Abandon unit and area delegations for this issue"] = "Aussetzen der Gliederungs-/Themenbereichsdelegation"; ["Abandon unit delegation"] = "Aussetzen der Gliederungsdelegation"; @@ -39,30 +64,22 @@ ["Abstention"] = "Enthaltung"; ["Abstention [many entries]"] = "Enthaltung"; ["Abstention [single entry]"] = "Enthaltung"; -["Accept invitation"] = "Einladung annehmen"; ["Accepted at"] = "Angenommen am/um"; -["Access level"] = "Berechtigung"; -["Activate account"] = "Account aktivieren"; +["Account history"] = "Kontoverlauf"; ["Active?"] = "Aktiv?"; -["Add alternative initiative to issue"] = "Alternative Initiative zum Thema hinzufügen"; -["Add my interest"] = "Mein Interesse anmelden"; -["Add new suggestion"] = "Neue Anregung hinzufügen"; -["Add new unit"] = "Neue Gliederung"; -["Add to my contacts"] = "Zu meinen Kontakten hinzufügen"; +["Add a new competing initiative to issue"] = "Eine neue konkurrierende Initiative hinzufügen"; +["Add a new suggestion for improvement"] = "Einen neuen Verbesserungsvorschlag"; ["Address"] = "Anschrift"; -["Admin"] = "Admin"; -["Admin menu"] = "Admin Menü"; ["Admin?"] = "Admin?"; +["Administrative notice:"] = "Administrativer Kommentar"; +["Admission"] = "Zulassung"; ["Admission time"] = "Zeit für die Zulassung"; ["Admitted"] = "zugelassen"; -["All areas"] = "Alle Themenbereiche"; -["All areas in my units"] = "Alle Themengebiete in meinen Gliederungen"; -["All issues"] = "Alle Themen"; -["All of them"] = "Alle Benachrichtigungen"; +["All areas in my units"] = "Alle Themenbereiche in meinen Gliederungen"; +["All fields are optional. Please enter only data which should be published."] = "Alle Felder sind optional. Bitte nur Daten eingeben, die veröffentlicht werden sollen."; +["All initiatives failed 2nd quorum"] = "Alle Initiativen sind am 2. Quorum gescheitert"; ["All units"] = "Alle Gliederungen"; -["Any"] = "Alle"; -["Any phase"] = "Alle Phasen"; -["Any state"] = "Alle Zustände"; +["Allowed policies"] = "Erlaubte Regelwerke"; ["Apply global delegation for this area (Currently: #{delegate_name} [#{scope}])"] = "Anwenden der globalen Delegation (Zur Zeit: #{delegate_name} [#{scope}])"; ["Apply global or area delegation for this issue (Currently: #{delegate_name} [#{scope}])"] = "Anwenden der globalen bzw. Themenbereichsdelegation (Zur Zeit: #{delegate_name} [#{scope}])"; ["Apply unit delegation for this area (Currently: #{delegate_name} [#{scope}])"] = "Anwenden der Gliederungsdelegation (Zur Zeit: #{delegate_name} [#{scope}])"; @@ -78,111 +95,91 @@ ["Approval [many entries]"] = "Zustimmung"; ["Approval [single entry]"] = "Zustimmung"; ["Approved"] = "Angenommen"; -["Are you sure?"] = "Sicher?"; +["Are you aware that revoking an initiative is irrevocable?"] = "Bist du dir bewusst, dass das Zurückziehen unwiderrufbar ist?"; ["Area"] = "Themenbereich"; -["Area '#{name}'"] = "Themenbereich '#{name}'"; ["Area delegation"] = "Delegation für Themenbereich"; ["Area list of '#{unit_name}'"] = "Themenbereiche in '#{unit_name}'"; -["Areas"] = "Themenbereiche"; +["As long as you are interested in this issue yourself, the delegation is suspended for this issue, but it will be applied again in the voting phase unless you vote yourself."] = "Solange du selber am Thema interessiert bist, wird die Delegation für dieses Thema ausgesetzt, jedoch während der Abstimmung erneut aktiv, es sei denn du stimmst selber ab."; +["As soon as one initiative of this issue reaches #{quorum} support, the issue will go into discussion phase."] = "Sobald eine Initiative des Themas das 1. Quorum von #{quorum} Unterstützern erreicht, geht das Thema in die Diskussionsphase über."; ["Author"] = "Autor"; +["Available policies"] = "Verfügbare Regelwerke"; ["Avatar"] = "Avatar"; ["Back"] = "Zurück"; -["Back to initiative"] = "Zurück zur Initiative"; -["Back to timeline"] = "Zurück zur Zeitachse"; -["Ballot of '#{member_name}' for issue ##{issue_id}"] = "Stimmzettel von '#{member_name}' für Thema ##{issue_id}"; +["Ballot of '#{member_name}'"] = "Stimmzettel von '#{member_name}'"; ["Become a member"] = "Mitglied werden"; +["Before creating a new issue, please check any existant issues before, if the topic is already in discussion."] = "Bitte vor dem Erstellen prüfen, ob ein anderes existierendes Thema passt!"; +["Best not admitted initiative"] = "Beste nicht zugelassene Initiative"; ["Birthday"] = "Geburtstag"; ["Broken delegations"] = "Kaputte Delegationen"; -["By delegation"] = "Durch Delegationen"; ["Calculation"] = "Auszählung"; ["Can't remove last initiator"] = "Der letzte Initiator kann nicht entfernt werden"; ["Can't send confirmation email"] = "Bestätigungs-E-Mail kann nicht versendet werden."; ["Cancel"] = "Abbrechen"; ["Cancel [nullify]"] = "Aufheben"; ["Cancel issue"] = "Thema abbrechen"; -["Cancel issue #{id}"] = "Thema #{id} abbrechen"; -["Cancel issue now"] = "Thema jetzt abbrechen"; -["Cancel refuse of invitation"] = "Ablehnung der Einladung aufheben"; -["Cancel registration"] = "Registrierung abbrechen"; -["Canceled"] = "Abgebrochen"; -["Canceled (before accepted due to revocation)"] = "Abgebrochen (in Neu-Phase, wegen Rückzug)"; -["Canceled (during discussion due to revocation)"] = "Abgebrochen (während Diskussion, wegen Rückzug)"; -["Canceled (during verification due to revocation)"] = "Abgebrochen (während Eingefroren-Phase, wegen Rückzug)"; -["Canceled (issue not accepted)"] = "Abgebrochen (Thema nicht akzeptiert)"; -["Canceled (no initiative admitted)"] = "Abgebrochen (Keine Initiative zugelassen)"; +["Cancel issue ##{id}"] = "Thema ##{id} abbrechen"; ["Canceled by administrative intervention"] = "Durch administrativen Eingriff abgebrochen"; -["Change area delegation"] = "Delegation für Themenbereich ändern"; -["Change email"] = "E-Mail-Adresse ändern"; ["Change email address"] = "E-Mail-Adresse ändern"; -["Change issue delegation"] = "Delegation für Thema ändern"; -["Change login"] = "Login ändern"; -["Change name"] = "Name ändern"; -["Change notification settings"] = "Benachrichtigungseinstellungen ändern"; ["Change order"] = "Sortierung ändern"; -["Change password"] = "Kennwort ändern"; -["Change unit delegation"] = "Delegation für Gliederung ändern"; -["Change vote"] = "Abstimmung ändern"; -["Change your login"] = "Deinen Anmeldenamen ändern"; -["Change your notification email address"] = "Deine E-Mail-Adresse für Benachrichtigungen ändern"; -["Change your password"] = "Dein Kennwort ändern"; -["Change your screen name"] = "Deinen Screen-Namen ändern"; -["Check delegations"] = "Delegationen pr\000fen"; -["Check your delegations!"] = "Delegationen pr\000fen!"; -["Choose initiator"] = "Initiator auswählen"; +["Check and enter personal data"] = "Persönliche Daten prüfen und eingeben"; +["Check your #{scope} delegation to '#{trustee_name}' for '#{context}'"] = "Delegation für #{scope} '#{context}' an '#{trustee_name}' prüfen"; +["Check your delegations!"] = "Delegationen prüfen!"; +["Check your outgoing delegations"] = "Ausgehende Delegation prüfen!"; +["Choose a formatting engine:"] = "Formatierungsmethode auswählen"; +["Choose a member to invite"] = "Wer soll eingeladen werden?"; +["Choose an initiator to remove"] = "Wer soll entfernt werden?"; ["Choose member"] = "Mitglied auswählen"; +["Choose your delegatee"] = "Delegierten ausw\000hlen"; ["Closed"] = "geschlossen"; ["Closed issues"] = "Geschlossene Themen"; -["Closed user group, please login to participate."] = "Geschlossene Benutzergruppe: Bitte melde dich an um teilzunehmen."; +["Closed user group"] = "Geschlossene Benutzergruppe"; ["Collective opinion of supporters"] = "Meinungsbild der Unterstützer"; -["Commit suggestion"] = "Anregung speichern"; ["Compare"] = "Vergleichen"; +["Comparision of revisions #{id1} and #{id2}"] = "Vergleich der Revisionen #{id1} und #{id2}"; +["Competing initiatives"] = "Konkurrierende Initiativen"; +["Competing initiatives failed the 2nd quorum (#{num}/#{den}):"] = "Konkurrierende Initiativen, die am 2. Quorum (#{num}/#{den}) scheiterten:"; +["Competing initiatives in pairwise comparison to best initiative:"] = "Konkurrierende Initiativen im Vergleich zur besten:"; +["Competing initiatives in pairwise comparison to winner:"] = "Konkurrierende Initiativen im Vergleich zum Gewinner"; ["Configure notifications now"] = "Benachrichtigungen jetzt konfigurieren"; ["Confirm"] = "Bestätigen"; +["Confirm notification address"] = "Benachrichtungsadresse bestätigen"; +["Confirm your email address"] = "E-Mail-Adresse bestätigen"; ["Confirmation code"] = "Bestätigungscode"; ["Confirmation code invalid!"] = "Bestätigungscode ist ungültig!"; -["Confirmed address"] = "Bestätigte E-Mail"; ["Contacts"] = "Kontakte"; -["Content"] = "Inhalt"; -["Counting starts soon"] = "Auszählung beginnt in Kürze"; -["Create / edit area"] = "Themengebiet anlegen / bearbeiten"; -["Create / edit policy"] = "Regelwerk anlegen / bearbeiten"; -["Create alternative initiative"] = "Alternative Initiative hinzufügen"; +["Create a new issue"] = "Neues Thema erstellen"; ["Create new area"] = "Neuen Themenbereich anlegen"; -["Create new issue"] = "Neues Thema anlegen"; ["Create new policy"] = "Neues Regelwerk anlegen"; ["Create new unit"] = "Neue Gliederung anlegen"; ["Created at"] = "Erzeugt am/um"; +["Current delegatee"] = "Aktueller Delegierter"; ["Current name"] = "Aktueller Name"; ["Current phase is already closed."] = "Die aktuelle Phase ist schon abgeschlossen."; ["Current status"] = "Aktueller Status"; -["Current trustee"] = "Aktueller Delegierter"; ["Current unit and area delegations need confirmation"] = "Aktuelle Gliederungs- und Themenbereichsdelegationen benötigen Bestätigung"; ["Current votings in areas you are member of and issues you are interested in:"] = "Jetzt laufende Abstimmungen zu Themen aus Deinen Themenbereichen oder solchen an denen Du interessiert bist:"; ["Currently no API key is set."] = "Zur Zeit ist kein API-Schlüssel festgelegt."; ["Currently required"] = "Zur Zeit benötigt"; -["Database download"] = "Datenbank herunterladen"; +["Currently this is the only initiative in this issue, because nobody started a competing initiative (yet)."] = "Zur Zeit ist dies die einzige Initiative in diesem Thema, da (noch) keine konkurrierende Initiative gestartet wurde."; ["Date format is not valid. Please use following format: YYYY-MM-DD"] = "Datumsformat nicht korrekt. Bitte verwende: JJJJ-MM-TT, also z.B. 1945-05-23"; ["Default Policy"] = "Standard-Regelwerk"; ["Degree"] = "Grad"; -["Delegate area"] = "Themengebiet delegieren"; +["Delegate area"] = "Themenbereich delegieren"; ["Delegate issue"] = "Thema delegieren"; ["Delegate unit"] = "Gliederung delegieren"; ["Delegation abandoned"] = "Delegation ausgesetzt"; -["Delegation turned off for area"] = "Delegation für Themengebiet ausgesetzt"; +["Delegation turned off for area"] = "Delegation für Themenbereich ausgesetzt"; ["Delegation turned off for issue"] = "Delegation für Thema ausgesetzt"; ["Delegations"] = "Delegationen"; -["Delete"] = "Löschen"; -["Delete filter"] = "Filter löschen"; +["Describe how the proposal and/or the reasons of the initiative could be improved"] = "Beschreibe, wie der Antrag und/oder die Begründung verbessert werden könnten"; ["Description"] = "Beschreibung"; ["Details"] = "Details"; ["Developer settings"] = "Einstellungen für Entwickler"; -["Diff"] = "Differenz"; -["Direct"] = "Direkt"; -["Direct and by delegation"] = "Direkt und delegiert"; +["Did the initiator implement this suggestion?"] = "Hat der Initiatior die Anregung umgesetzt?"; ["Direct majority"] = "Direkte Mehrheit"; -["Direct majority denumerator"] = "Direkte Mehrheit Denumerator"; +["Direct majority denominator"] = "Direkte Mehrheit Nenner"; ["Direct majority non negative"] = "Direkte Mehrheit Nicht-Negative"; -["Direct majority numerator"] = "Direkte Mehrheit Numerator"; +["Direct majority numerator"] = "Direkte Mehrheit Zähler"; ["Direct majority positive"] = "Direkte Mehrheit Positv"; ["Disapproval (prefer to last block) [many entries]"] = "Ablehnung (jedoch Bevorzugung gegenüber letztem Ablehnungsblock)"; ["Disapproval (prefer to last block) [single entry]"] = "Ablehnung (jedoch Bevorzugung gegenüber letztem Ablehnungsblock)"; @@ -192,57 +189,71 @@ ["Disapproval (prefer to lower blocks) [single entry]"] = "Ablehnung (jedoch Bevorzugung gegenüber unteren Ablehnungsblöcken)"; ["Disapproval [many entries]"] = "Ablehnung"; ["Disapproval [single entry]"] = "Ablehnung"; -["Discard voting"] = "Abstimmung zurückziehen"; -["Discuss with initiators"] = "Diskussion mit den Initiatoren"; +["Disapproved"] = "Abgelehnt"; +["Discard my vote"] = "Meine Stimme zurückziehen"; ["Discussion"] = "Diskussion"; +["Discussion #{time_info}"] = false; ["Discussion URL"] = "Diskussions-URL"; -["Discussion on issue"] = "Diskussion zum Thema"; ["Discussion started"] = "Diskussion gestartet"; -["Discussion starts soon"] = "Diskussion startet in Kürze"; ["Discussion time"] = "Zeit für die Diskussion"; -["Discussion with initiators"] = "Diskussion mit den Initiatoren"; -["Do not vote directly"] = "Nicht selbst abstimmen"; +["Do you want to suggest to support another initiative?"] = "Möchtest du eine andere Initiative empfehlen?"; ["Download"] = "Download"; ["Download database export"] = "Datenbankexport herunterladen"; ["Download documents"] = "Dokumente herunterladen"; -["Draft"] = "Entwurf"; +["Draft history"] = "Entwurfshistorie"; +["Draft revision #{id}"] = "Entwurf Revision #{id}"; +["During the discussion phase the issue is debated between initiators while the initiatives are improved by suggestions from the supporters."] = "Während der Diskussionsphase wird das Thema zwischen den Initiatoren debattiert, während die Entwurfstext der Initiativen durch Verbesserungsvorschläge der Unterstützer weiterentwickelt wird."; +["During the verification phase the initiative drafts cannot be changed anymore."] = "Während der Überprüfungsphase kann der Text der Initiative nicht mehr geändert werden."; ["Edit"] = "Bearbeiten"; +["Edit again"] = "Nochmal bearbeiten"; ["Edit areas"] = "Themenbereiche bearbeiten"; -["Edit draft"] = "Entwurf bearbeiten"; ["Edit initiative"] = "Initiative bearbeiten"; -["Edit my page"] = "Meine Seite bearbeiten"; -["Edit my profile"] = "Mein Profil bearbeiten"; ["Edit profile"] = "Profil bearbeiten"; +["Edit voting comment"] = "Abstimmungskommentar bearbeiten"; +["Edit your profile data"] = "Profildaten bearbeiten"; ["Eligible as winner"] = "Als Gewinner qualifiziert"; +["Eligible members (#{count})"] = "Stimmberechtigte Teilnehmer (#{count})"; ["Eligible voters"] = "Stimmberechtigte"; ["Email address"] = "E-Mail-Adresse"; ["Email address confirmation"] = "Bestätigung der E-Mail-Adresse"; +["Email address for notifications"] = "E-Mail-Adresse für Benachrichtungen"; ["Email address is confirmed now"] = "E-Mail-Adresse ist jetzt bestätigt"; ["Email address too short!"] = "E-Mail-Adresse ist zu kurz!"; ["Email confirmation request"] = "Bestätigung deiner E-Mail-Adresse"; -["Empty help text: #{id}.#{lang}.txt"] = "Leerer Hilfe-Text: #{id}.#{lang}.txt"; +["Emphasis"] = "Hervorhebung"; +["Enter a new email address:"] = "Neue E-Mail-Adresse eingeben:"; +["Enter a new login name"] = "Neuen Anmeldenamen eingeben:"; +["Enter a new password:"] = "Neues Kennwort eingeben"; +["Enter a new screen name:"] = "Neuen Screen-Namen eingeben"; +["Enter a title for your initiative (max. 140 chars):"] = "Einen Titel für die Iniative eingeben (max. 140 Zeichen)"; +["Enter your current password:"] = "Bisheriges Kennwort eingeben:"; +["Enter your new password again please:"] = "Das neue Kennwort bitte nocheinmal eingeben:"; +["Enter your proposal and/or reasons"] = "Antrag und/oder Begründung eingeben"; +["Enter your proposal and/or reasons:"] = "Antrag und/oder Begründung eingeben:"; ["Error while converting image. Please note, that only JPG files are supported!"] = "Fehler beim Konvertieren des Bilds. Bitte beachte, dass nur JPG-Dateien unterstützt werden."; ["Error while updating member, database reported:

(#{errormessage})"] = "Fehler beim aktualisieren des Mitglieds, die Datenbank berichtet folgenden Fehler:

(#{errormessage})"; ["Etherpad authentication failed"] = "Etherpad-Anmeldung fehlgeschlagen"; ["Event #{id} -> #{num} members"] = false; -["Everything"] = "Alles"; ["External memberships"] = "Externe Mitgliedschaften"; ["External posts"] = "Externe Ämter"; +["Failed #{sign}#{num}/#{den}"] = "Gescheitert #{sign}#{num}/#{den}"; +["Failed 1st quorum"] = "Am 1. Quorum gescheitert"; ["Finish delegation check"] = "Delegationsprüfung abschließen"; ["Finish voting"] = "Stimmabgabe abschließen"; -["Finished"] = "Abgeschlossen"; -["Finished (with winner)"] = "Abgeschlossen (mit Gewinner)"; -["Finished (without winner)"] = "Abgeschlossen (ohne Gewinner)"; -["Forgot login name?"] = "Anmeldename vergessen?"; +["Finished with winner"] = "Mit Gewinner abgeschlossen"; +["For numbered items use a digit (e.g. 1) followed by a dot (.) and a space"] = "Für nummerierte Listen verwende eine Ziffer (e.g. 1) gefolgt von einem Punkt (.) und einem Leerschritt"; +["For which issue phases do you like to receive notification emails?"] = "Für welche Themenphasen sollen E-Mail-Benachrichtigungen versendet werden?"; +["Forgot login name?"] = "Anmeldenamen vergessen?"; ["Forgot password?"] = "Kennwort vergessen?"; -["Free timing"] = "Freie Zeitsteuerung"; -["Friday"] = "Freitag"; +["Formatting help"] = "Hilfe zur Formatierung"; +["Free timing:"] = "Freie Zeitsteuerung:"; ["Frozen"] = "Eingefroren"; ["Fully frozen at"] = "Ganz eingefroren am/um"; ["Generate API key"] = "API-Schlüssel erzeugen"; ["Global delegation"] = "Globale Delegation"; -["Global search"] = "Globale Suche"; +["Go back to home page"] = "Zurück zur Startseite"; ["Half frozen at"] = "Halb eingefroren am/um"; +["Headlines"] = "Überschriften"; ["Hello\n\n"] = "Hallo\n\n"; ["Hello "] = "Hallo "; ["Hello,\n\n"] = "Hallo, "; @@ -250,85 +261,112 @@ ["Help for: #{text}"] = "Hilfe zu: #{text}"; ["Hide"] = "Verstecken"; ["Hide active units"] = "Aktive units ausblenden"; -["Hide filter details"] = "Filter-Details verstecken"; -["Hide this help message"] = "Diesen Hilfetext ausblenden"; ["Hint"] = "Hinweis"; -["History"] = "Historie"; +["History"] = "Zeitlicher Verlauf"; ["Home"] = "Startseite"; +["How important is your suggestions for you?"] = "Wie wichtig ist diese Anregung?"; +["How this member voted"] = "Wie dieses Mitglied abgestimmt hat"; ["I consider suggestion as"] = "Ich halte die Anregung für"; -["I like to receive notifications by email about events in my areas and issues:"] = "Ich möchte per E-Mail über die folgenden Ereignisse in meinen Themenbereichen und Themen informiert werden:"; +["I do not like to hear from this member"] = "Ich möchte nichts mehr von diesem Mitglied mitbekommen"; +["I do not like to receive notifications by email"] = "Ich möchte keine Benachrichtigungen per E-Mail erhalten"; +["I don't like any of the initiative in this issue and I want to add my opinion or counter proposal"] = "Ich mag keine der Initiativen in diesem Thema und möchte meine Meinung oder Gegenvorschlag einbringen"; +["I don't like this initiative and I want to add my opinion or counter proposal"] = "Ich mag diese Initiative nicht und möchte meine Meinung oder Gegenvorschlag einbringen"; +["I don't like to vote this issue (myself):"] = "Ich möchte für dieses Thema nicht (selber) abstimmen:"; +["I like this initiative and I want to support it"] = "Ich mag diese Initiative und möchte sie unterstützen"; +["I like to change/revoke my vote:"] = "Ich möchte meine Stimme ändern/widerrufen"; +["I like to receive notifications"] = "Ich möchte Benachrichtigungen erhalten"; +["I like to vote on this issue:"] = "Ich möchte für dieses Thema abstimmen"; +["I understand, that this is not revocable"] = "Ich verstehe, dass dies nicht widerrufbar ist"; +["I want to change account settings"] = "Ich möchte meine Kontoeinstellungen ändern"; +["I want to change the interface language"] = "Ich möchte die Sprache ändern"; +["I want to customize my profile"] = "Ich möchte mein Profil anpassen"; +["I want to delegate my vote"] = "Ich möchte meine Stimme delegieren"; +["I want to delegate this issue"] = "Ich möchte dieses Thema delegieren"; +["I want to delegate this organizational unit"] = "Ich möchte diese Gliederung delegieren"; +["I want to delegate this subject area"] = "Ich möchte diesen Themenbereich delegieren"; +["I want to improve this initiative"] = "Ich möchte die Initiative verbessern"; +["I want to know whats going on"] = "Ich möchte wissen was los ist"; +["I want to learn more about LiquidFeedback"] = "Ich möchte mehr über LiquidFeedback lernen"; +["I want to logout"] = "Ich möchte mich ausloggen"; +["I want to manage my saved contacts"] = "Ich möchte meine gespeicherten Kontakte bearbeiten"; +["I want to participate in this issue"] = "Ich möchte an diesem Thema teilnehmen"; +["I want to participate in this subject area"] = "Ich möchte an diesem Themenbereich teilnehmen"; +["I want to save this member as contact (i.e. to use as delegatee)"] = "Ich möchte dieses Mitglied als Kontakt speichern (z.B. als Delegationsempfänger)"; +["I want to start a new initiative"] = "Ich möchte eine neue Initiative starten"; +["I want to stay informed"] = "Ich möchte informiert bleiben"; +["I want to take a look at other organizational units"] = "Ich möchte einen Blick auf andere Gliederungen werfen"; +["I'm interested in this issue"] = "Ich bin an diesem Thema interessiert"; +["I'm supporting this initiative"] = "Ich unterstütze diese Initiative"; ["Id"] = "Id"; ["Identification"] = "Identifikation"; ["If this link is not working, please open following url in your web browser:\n\n"] = "Sollte der Link nicht funktionieren, öffne bitte die folgenden URL in Deinem Web-Browser:\n\n"; -["Ignore Areas"] = "Ignoriere Bereiche"; +["If you cannot find any appropriate existing issue, "] = "Wenn kein passendes Thema existiert, "; ["Ignore initiative"] = "Initiative ignorieren"; -["Ignore member"] = "Mitglied ignorieren"; -["Images"] = "Bilder"; ["Implicitly admitted"] = "Implizit zugelassen"; ["Incoming delegations"] = "Eingehende Delegationen"; +["Incoming delegations for '#{member_name}'"] = "Eingehende Delegationen für '#{member_name}'"; +["Incoming delegations for '#{member}'"] = "Eingehende Delegationen für '#{member}'"; +["Indent sub items with spaces"] = "Unterpunkte mit Leerschritt einrücken"; ["Index"] = "Positionsnummer"; ["Indirect majority"] = "Indirekte Mehrheit"; -["Indirect majority denumerator"] = "Indirekte Mehrheit Denumerator"; +["Indirect majority denominator"] = "Indirekte Mehrheit Nenner"; ["Indirect majority non negative"] = "Indirekte Mehrheit Nicht-Negativ"; -["Indirect majority numerator"] = "Indirekte Mehrheit Numerator"; +["Indirect majority numerator"] = "Indirekte Mehrheit Zähler"; ["Indirect majority positive"] = "Indirekte Mehrheit Positiv"; -["Information about the available policies"] = "Informationen zu den verfügbaren Regelwerken"; -["Initiated"] = "Initiiert"; -["Initiative"] = "Initiative"; -["Initiative ##{id}"] = "Initiative ##{id}"; -["Initiative events"] = "Initiativen-Ereignisse"; -["Initiative i#{id}: #{name}"] = "Initiative i#{id}: #{name}"; ["Initiative is revoked now"] = "Initiative ist jetzt zurückgezogen"; +["Initiative not admitted"] = "Initiative nicht zugelassen"; ["Initiative quorum"] = "Quorum Initiative"; -["Initiative quorum denumerator"] = "Initiativ-Quorum Nenner"; +["Initiative quorum denominator"] = "Initiative-Quroum Nenner"; ["Initiative quorum numerator"] = "Initiativ-Quorum Zähler"; ["Initiative revoked"] = "Initiative zurückgezogen"; ["Initiative successfully created"] = "Initiative erfolgreich erzeugt"; ["Initiative successfully updated"] = "Initiative erfolgreich aktualisiert"; ["Initiative: "] = "Initiative: "; +["Initiatives"] = "Initiativen"; +["Initiatives and issues"] = "Initiativen und Themen"; +["Initiatives created by this member"] = "Initiativen von diesem Mitglied"; ["Initiatives that invited you to become initiator:"] = "Initiative, die Dich eingeladen haben, Initiator zu werden:"; ["Initiator invites"] = "Einladungen"; ["Initiators"] = "Initiatoren"; -["Interest not existent"] = "Interesse existiert nicht"; +["Interest already removed"] = "Interesse wurde bereits abgemeldet"; ["Interest removed"] = "Interesse entfernt"; ["Interest updated"] = "Interesse aktualisiert"; -["Interested"] = "Interessiert"; -["Interested members"] = "Interessierte Mitglieder"; +["Interested members"] = "Interessierte Teilnehmer"; ["Internal posts"] = "Interne Ämter"; ["Interval format:"] = "Intervall-Format"; +["Introduction"] = "Einführung"; ["Invalid login name or password!"] = "Anmeldename oder Kennwort ungültig"; -["Invalid query"] = "Ungültige Anfrage"; ["Invitation has been refused"] = "Einladung wurde widerrufen"; ["Invitation to LiquidFeedback"] = "Einladung zu LiquidFeedback"; ["Invite an initiator to initiative"] = "Initiator zur Initiative einladen"; ["Invite code"] = "Einladungscode"; -["Invite initiator"] = "Initiator einladen"; +["Invite member"] = "Mitglied einladen"; ["Invited"] = "Eingeladen"; -["Issue"] = "Thema"; +["Issue #"] = "Thema #"; ["Issue ##{id}"] = "Thema ##{id}"; -["Issue ID"] = "Thema #"; -["Issue accepted"] = "Thema akzeptiert"; -["Issue canceled"] = "Thema abgebrochen"; +["Issue ##{issue_id}: #{initiative_name}"] = "Thema ##{issue_id}: #{initiative_name}"; ["Issue delegation"] = "Issue-Delegation"; -["Issue events"] = "Themen-Ereignisse"; -["Issue finished"] = "Thema abgeschlossen"; -["Issue finished without voting"] = "Thema ohne Abstimmung abgeschlossen"; -["Issue frozen"] = "Thema eingefroren"; ["Issue has been canceled"] = "Thema wurde abgebrochen"; -["Issue pad"] = "Pad zum Thema"; ["Issue quorum"] = "Quorum Thema"; -["Issue quorum denumerator"] = "Themen-Quorum Nenner"; +["Issue quorum denominator"] = "Themen-Quroum Nenner"; ["Issue quorum numerator"] = "Themen-Quorum Zähler"; ["Issue reached next phase"] = "Thema hat die nächste Phase erreicht"; +["Issues in admission phase"] = "Themen in Zulassung"; +["Issues in discussion phase"] = "Themen in Diskussion"; +["Issues in verification phase"] = "Themen in Überprüfung"; +["Issues in voting phase"] = "Themen in Abstimmung"; ["Issues:"] = "Themen:"; ["JavaScript is disabled or not available."] = "JavaScript ist abgeschaltet oder nicht verfügbar."; ["Last activity (updated daily)"] = "Letzte Aktivität (täglich aktualisiert)"; -["Last snapshot:"] = "Letzte Auszählung:"; -["Latest draft created at #{date} #{time}"] = "Letzter Entwurf vom #{date} um #{time}"; +["Last counting:"] = "Letzte Auszählung"; +["Latest activity"] = "Letzte Aktivität"; +["Latest approved issue"] = false; +["Latest disapproved issue"] = false; ["Latest events"] = "Letzte Ereignisse"; -["License"] = "Lizenz"; +["Links"] = "Links"; ["LiquidFeedback"] = "LiquidFeedback"; -["List all revisions (#{count})"] = "Zeige alle Versionen (#{count})"; +["Lists"] = "Listen"; +["Lists must be preceeded and followed by at least one blank line"] = "Listen müssen von Leerzeilen umgeben sein"; ["Lock member?"] = "Mitglied sperren?"; ["Locked?"] = "Gesperrt?"; ["Login"] = "Anmeldung"; @@ -337,117 +375,102 @@ ["Login-Name: "] = "Anmeldename: "; ["Logout"] = "Abmelden"; ["Logout successful"] = "Abmeldung erfolgreich"; -["Manage filter"] = "Filter verwalten"; -["Manage timeline filters"] = "Zeitachsen-Filter verwalten"; +["Make your choice by placing the initiatives"] = "Treffe eine Wahl indem du die Initiativen verschiebst"; +["Manage system settings"] = "Systemeinstellungen verwalten"; ["Member"] = "Mitglied"; -["Member '#{member}'"] = "Mitglied '#{member}'"; ["Member has been removed from initiators"] = "Mitglied wurde von den Initiatoren entfernt"; ["Member has been removed from your contacts"] = "Mitglied wurde aus Deinen Kontakten entfernt"; ["Member has not approved latest draft"] = "Mitglied hat den letzten Entwurf noch nicht angenommen"; -["Member has voting privileges for this unit"] = "Mitglied hat Stimmrecht in dieser Gliederung"; ["Member inactive?"] = "Mitglied inaktiv?"; ["Member is already saved in your contacts!"] = "Mitglied ist schon in Deinen Kontakten!"; ["Member is not participating in any of the #{count} areas in this unit"] = "Mitglied nimmt an keinem der #{count} Themenbereiche dieser Gliederung teil"; ["Member is not participating in the only area of the unit"] = "Mitglied nimmt am einzigen Themenbereich der Gliederung nicht teil"; ["Member is now invited to be initiator"] = "Mitglied ist jetzt als Initiator eingeladen"; -["Member is participating in this area"] = "Mitglied ist Teilnehmer im Themenbereich"; ["Member list"] = "Mitgliederliste"; ["Member menu"] = "Mitglieds-Menü"; ["Member name"] = "Mitglied Name"; -["Member name history for '#{name}'"] = "Namenshistorie für '#{name}'"; -["Member of area"] = "Mitglied des Themenbereichs"; -["Member page"] = "Mitgliederseite"; ["Member successfully registered"] = "Mitglied erfolgreich registriert"; ["Member successfully updated"] = "Mitglied erfolgreich aktualisert"; -["Member: '#{identification}' (#{name})"] = "Mitglied: '#{identification}' (#{name})"; ["Members"] = "Mitglieder"; -["Membership not existent"] = "Mitgliedschaft existiert nicht"; -["Membership removed"] = "Mitgliedschaft entfernt"; -["Membership updated"] = "Mitgliedschaft aktualisiert"; ["Memberships"] = "Mitgliedschaften"; ["Missing help text: #{id}.#{lang}.txt"] = "Fehlender Hilfetext: #{id}.#{lang}.txt"; ["Mobile phone"] = "Mobiltelefon"; -["Monday"] = "Montag"; ["Move down"] = "Runter schieben"; ["Move up"] = "Hoch schieben"; -["My areas"] = "Meine Themengebiete"; -["My areas and issues"] = "Meine Themengebiete und Themen"; +["My areas"] = "Meine Themenbereiche"; ["My opinion"] = "Meine Meinung"; -["My units"] = "Meine Gliederungen"; ["Name"] = "Name"; ["New"] = "Neu"; -["New address"] = "Neue E-Mail-Adresse"; -["New draft"] = "Neuer Entwurf"; -["New draft has been added to initiative"] = "Neuer Entwurf wurde der Initiative hinzugefügt"; +["New area"] = "Neues Themenbereich"; +["New draft for initiative '#{initiative_name}'"] = "Neuer Entwurfstext von Initiative '#{initiative_name}'"; ["New drafts for #{count} initiative(s) you are supporting"] = "Für #{count} von dir unterstützte Iniativen gibt es neue Entwürfe"; ["New initiative"] = "Neue Initiative"; ["New initiative draft"] = "Neuer Entwurfstext der Initiative"; ["New issue"] = "Neues Thema"; -["New password"] = "Neues Kennwort"; +["New member"] = "Neues Mitglied"; +["New organizational unit"] = "Neue Gliederung"; ["New passwords does not match."] = "Du hast nicht zweimal das gleiche Kennwort eingegeben"; ["New passwords is too short."] = "Das neue Kennwort ist zu kurz"; +["New policy"] = "Neues Regelwerk"; ["New suggestion"] = "Neue Anregung"; ["Newest"] = "Neueste"; ["No"] = "Nein"; +["No (not yet)"] = "Nein (noch nicht)"; ["No admission needed"] = "Keine Zulassung nötig"; ["No changes to your images were made"] = "An Deinen Bildern wurde nichts geändert"; ["No default"] = "Kein Standard"; ["No delegation"] = "Keine Delegation"; -["No events selected to list"] = "Keine Ereignisse ausgewählt"; +["No matching issues found"] = "Keine passenden Themen gefunden"; +["No matching members found"] = "Keine passenden Mitglieder gefunden"; ["No more events available"] = "Keine weiteren Ereignisse verfügbar"; ["No multistage majority"] = "Keine mehrstufigen Mehrheiten"; -["No notifications at all"] = "Gar keine Benachrichtigungen"; -["No potential supporters"] = "Keine potentiellen Unterstützer"; -["No potential supporters (before begin of voting)"] = "Keine potentiellen Unterstützer (zum Abstimmungsbeginn)"; +["No published contacts"] = "Keiner Kontakte veröffentlicht"; +["No results for this selection"] = "Keine Ergebnisse für diese Auswahl"; ["No reverse beat path"] = "Kein rückwärtsgerichteter Schlagpfad"; ["No suggestions"] = "Keine Anregungen"; ["No suggestions yet"] = "Noch keine Anregungen"; -["No supporters"] = "Keine Unterstützer"; -["No supporters (before begin of voting)"] = "Keine Unterstützer (zum Abstimmungsbeginn)"; ["Not a member"] = "Kein Mitglied"; -["Not accepted yet"] = "Bisher nicht angenommen"; -["Not approved"] = "Nicht angenommen"; -["Not approved (rank #{rank})"] = "Nicht angenommen (Rang #{rank})"; -["Not voted"] = "Nicht abgestimmt"; ["Not voted issues"] = "Nicht abgestimmt"; ["Notification address unconfirmed"] = "E-Mail-Adresse für Benachrichtigungen unbestätigt"; ["Notification email"] = "E-Mail für Benachrichtigungs"; ["Notification level not set yet"] = "Benachrichtigungseinstellungen noch nicht vorgenommen"; -["Notification settings"] = "Benachrichtigungseinstellungen"; +["Notifications"] = "Benachrichtigungen"; +["Notifications are only send to you about events in the subject areas you subscribed, the issues you are interested in and the initiatives you are supporting."] = "Benachrichtigungen werden nur für Ereignisse versendet, die deine Themenbereiche, Themen, und unterstützten Intiativen betreffen."; ["Number of incoming delegations, follow link to see more details"] = "Anzahl eingehender Delegationen, Link folgen für mehr Details"; ["OK"] = "OK"; -["Old password"] = "Altes Kennwort"; ["Old password is wrong"] = "Das alte Kennwort ist falsch"; ["Oldest"] = "Älteste"; ["On that page please enter the confirmation code:\n\n"] = "Auf dieser Seite gib bitten den folgenden Code ein:\n\n"; ["On that page please enter the invite key:\n\n"] = "Auf dieser Seite gib den folgenden Code ein:\n\n"; ["On that page please enter the reset code:\n\n"] = "Auf dieser Seite gib bitte den folgenden Rücksetzcode ein:\n\n"; +["On this issue can be voted now."] = "Über dieses Thema kann jetzt abgestimmt werden."; ["One issue"] = "Ein Thema"; ["One issue you are interested in"] = "Ein Thema, das Dich interessiert"; -["One more area in this unit"] = "Ein weiteres Themengebiet in dieser Gliederung"; +["One more area in this unit"] = "Ein weiterer Themenbereich in dieser Gliederung"; ["One of them have an area delegation set"] = "Bei einem davon ist eine Delegation für den Themenbereich gesetzt"; -["One step back"] = "Ein Schritt zurück"; ["Only for issues reaching the discussion phase"] = "Nur für Themen, die die Diskussion erreichen."; -["Only for issues reaching the frozen phase"] = "Nur für Themen, die die Phase Eingefroren erreichen."; +["Only for issues reaching the verification phase"] = "Nur für Themen, die die Überprüfung erreichen"; ["Only for issues reaching the voting phase"] = "Nur für Themen, die die Abstimmung erreichen."; -["Open"] = "Offen"; ["Open initiatives you are supporting which has been updated their draft:"] = "Offene, von dir unterstützte Initiativen, deren Antragstext aktualisiert wurde:"; ["Open issues"] = "Offene Themen"; +["Open the appropriate subject area where your issue fits in and follow the instruction on that page."] = "Den passenden Themenbereich öffnen und dort den Anweisungen folgen."; ["Opinions"] = "Meinungen"; ["Options"] = "Optionen"; ["Organizational unit"] = "Organisationseinheit"; +["Organizational units"] = "Organisationseinheiten"; +["Organizational units and subject areas"] = "Organisationseinheiten und Themenbereiche"; ["Other failures"] = "Weitere Mängel"; ["Outgoing delegations"] = "Ausgehende Delegationen"; +["Page not found"] = "Seite nicht gefunden"; +["Paragraphs"] = "Absätze"; ["Parent unit"] = "Übergeordnete Gliederung"; -["Participants"] = "Teilnehmer"; -["Participate in this area"] = "An diesem Themengebiet teilnehmen"; ["Password"] = "Kennwort"; ["Password (repeat)"] = "Kennwort (wiederholen)"; ["Password has been reset successfully"] = "Kennwort wurde erfolgreich zurückgesetzt"; ["Password reset request"] = "Kennwort-Rücksetzung anfordern"; ["Passwords don't match!"] = "Kennwörter stimmen nicht überein!"; ["Passwords must consist of at least 8 characters!"] = "Das Kennwort muss zumindest 8 Zeichen lang sein!"; -["Phases"] = "Phasen"; +["Phase durations"] = "Phasendauer"; ["Phone"] = "Telefon"; ["Photo"] = "Foto"; ["Please choose a login name. This name will not be shown to others and is used only by you to login into the system. The login name is case sensitive."] = "Bitte wähle einen Anmeldenamen. Dieser wird anderen nicht gezeigt und nur von Dir zum Anmelden verwendet. Groß- und Kleinschreibung wird berücksichtigt."; @@ -455,13 +478,15 @@ ["Please choose a name, i.e. your real name or your nick name. This name will be shown to others to identify you."] = "Wähle einen Namen, z. B. Deinen Real- oder Nicknamen. Dieser wird anderen angezeigt um Dich zu identifizieren."; ["Please choose a password and enter it twice. The password is case sensitive."] = "Bitte wähle ein Kennwort und gib es zweimal ein. Groß- und Kleinschreibung wird berücksichtigt."; ["Please choose a policy"] = "Bitte wähle ein Regelwerk"; +["Please choose a policy for the new issue:"] = "Bitte ein Regelwerk für das neue Thema auswählen:"; +["Please choose an area name"] = "Bitte einen Namen für den Themenbereich wählen"; ["Please choose two different versions of the draft to compare"] = "Bitte wähle zwei verschiedene Versionen des Entwurfs, um sie zu vergleichen."; -["Please choose two versions of the draft to compare"] = "Bitte wähle zwei Versionen des Entwurfs, um sie zu vergleichen."; ["Please confirm your email address"] = "Bitte bestätige Deine E-Mail-Adresse"; ["Please confirm your email address by clicking the following link:\n\n"] = "Bitte bestätige Deine E-Mail-Adresse durch Klick auf folgenden Link:\n\n"; ["Please decide for each delegation to confirm or to revoke it!"] = "Für jede Delegation muss eine Entscheidung getroffen werden!"; +["Please enter a meaningful title for your initiative!"] = "Bitte einen aussagekräftigen Titel für die Initiative eingeben!"; ["Please enter the email reset code you have received:"] = "Bitte gib den Rücksetzcode ein, den Du erhalten hast:"; -["Please enter the invite code you've received."] = "Bitte gib den Einladungscode ein, den Du erhalten hast."; +["Please enter the invite code you've received"] = "Bitte den erhaltenen Einladungscode eingeben"; ["Please enter your email address. This address will be used for automatic notifications (if you request them) and in case you've lost your password. This address will not be published. After registration you will receive an email with a confirmation link."] = "Bitte gib Deine E-Mail-Adresse ein. Diese Adresse wird für automatische Benachrichtigungen (wenn Du diese anforderst) sowie zum Zurücksetzen des Kennworts verwendet. Diese Adresse wird nicht veröffentlicht. Nach Abschluss der Registrierung wirst Du eine E-Mail mit einem Link zum Bestätigen der Adresse erhalten."; ["Please enter your email address. You will receive an email with your login name."] = "Bitte die E-Mail-Adresse eingeben. An diese wird eine Nachricht mit dem zugehörigen Anmeldenamen versendet."; ["Please enter your login name. You will receive an email with a link to reset your password."] = "Bitte gib Deinen Anmeldenamen ein. Du wirst eine E-Mail mit einem Link zum Zurücksetzen des Kennworts erhalten."; @@ -474,102 +499,110 @@ ["Polling mode"] = "Befragungsmodus"; ["Population"] = "Grundgesamtheit"; ["Posts"] = "Ämter"; -["Potential supported"] = "Potentiell unterstützt"; -["Potential supporters"] = "Potentielle Unterstützer"; -["Potential supporters (before begin of voting)"] = "Potentielle Unterstützer (zum Abstimmungsbeginn)"; -["Potentially supported"] = "Potentiell unterstützt"; +["Preference comparison"] = "Präferenzvergleich"; +["Preference voting"] = "Präferenzabstimmung"; ["Preview"] = "Vorschau"; -["Preview voting comment"] = "Vorschau Abstimmmungskommentar"; -["Proceed with registration"] = "Registrierung fortsetzen"; +["Preview of delegation"] = "Vorschau der Delegation"; +["Preview of voting ballot"] = "Vorschau des Stimmzettels"; +["Private contacts"] = "Kontakte (nicht veröffentlicht)"; ["Profession"] = "Beruf"; -["Profile"] = "Profil"; -["Public administrative notice:"] = "Administrativer Hinweistext (öffentlich)"; ["Publish"] = "Veröffentlichen"; +["Publish now"] = "Jetzt veröffentlichen"; ["Published"] = "veröffentlicht"; -["Quorum"] = "Quorum"; +["Published contacts"] = "Veröffentlichte Kontakte"; +["Put **double asterisks** around a phrase to make it bold"] = "Für fetten Text, diesen in **doppelten Sternchen** einschließen"; +["Put *asterisks* or around a phrase to make it italic"] = "Für kursiven Text, diesen in *einfache Sternchen* einschließen"; +["Put a hypen (-) or asterisk (*) followed by a space in front of each item"] = "Einen Strich (-) oder Sternchen (*) gefolgt von einem Leerschritt vor jeden Listenpunkt setzen"; +["Quorums"] = "Quoren"; +["Reached #{sign}#{num}/#{den}"] = "#{sign}#{num}/#{den} erreicht"; +["Read and accept the terms and choose a password"] = "Nutzungsbedingungen akzeptieren und ein Kennwort wählen"; +["Read more"] = "Mehr lesen"; ["Real name"] = "Realname"; -["Refresh support to current draft"] = "Unterstützung auf aktuellen Entwurf aktualisieren"; -["Refuse invitation"] = "Einladung ablehnen"; +["Recover login name"] = "Login-Namen wiederherstellen"; ["Register new member"] = "Neues Mitglied registrieren"; +["Registered members (#{count})"] = "Registrierte Teilnehmer (#{count})"; ["Registration"] = "Registrierung"; ["Registration (step 1 of 3: Invite code)"] = "Registrierung (Schritt 1 von 3: Einladungscode)"; ["Registration (step 2 of 3: Personal information)"] = "Registrierung (Schritt 2 von 3: Persönliche Daten)"; ["Registration (step 3 of 3: Terms of use and password)"] = "Registrierung (Schritt 3 von 3: Nutzungsbedingungen und Kennwort)"; ["Rejected"] = "Abgelehnt"; +["Rejected (rank #{rank})"] = "Abgelehnt (#{rank}. Platz)"; ["Remove"] = "Entfernen"; -["Remove from contacts"] = "Aus den Kontakten entfernen"; +["Remove an initiator from initiative"] = "Einen Initiator entfernen"; ["Remove initiator"] = "Initiator entfernen"; -["Remove initiator from initiative"] = "Initiator von der Initiative entfernen"; ["Rendered"] = "Formatiert"; -["Repeat new password"] = "Neues Kennwort wiederholen"; ["Request email with login name"] = "E-Mail mit Anmeldename anfordern"; -["Request password reset link"] = "Link zum Rücksetzen des Kennworts anfordern"; +["Request password reset link"] = "Rücksetzlink per E-Mail anfordern"; ["Resend activation email to '#{email}'"] = "E-Mail mit Aktivierungslink erneut an '#{email}' senden"; ["Reset code"] = "Rücksetzcode"; ["Reset code is invalid!"] = "Rücksetzcode ist ungültig"; ["Reset password"] = "Kennwort zurücksetzen"; ["Revoke initiative"] = "Initiative zurückziehen"; +["Revoke now"] = "Jetzt zurückziehen"; +["Revoked (during admission)"] = "Zurückgezogen (während der Zulassung)"; +["Revoked (during discussion)"] = "Zurückgezogen (während der Diskussion)"; +["Revoked (during verification)"] = "Zurückgezogen (während der Überprüfung)"; ["Revoked at"] = "Zurückgezogen am/um"; -["Saturday"] = "Samstag"; +["Rules of procedure"] = "Regelwerke"; ["Save"] = "Speichern"; -["Save current filter"] = "Aktuellen Filter speichern"; -["Save timeline filters"] = "Zeitachsen-Filter speichern"; -["Saved as contact"] = "Als Kontakt gespeichert"; +["Save new password"] = "Neues Kennwort speichern"; +["Save voting comment"] = "Abstimmungskommentar speichern"; ["Saved contacts"] = "Gespeicherte Kontakte"; ["Schulze rank"] = "Schulze-Rang"; ["Screen name"] = "Screen-Name"; ["Search"] = "Suchen"; -["Search context"] = "Suchkontext"; -["Search for issues"] = "Nach Themen suchen"; -["Search for members"] = "Nach Mitgliedern suchen"; ["Search initiatives"] = "Suche Initiativen"; ["Search issues"] = "Suche Themen"; ["Search members"] = "Suche Mitglieder"; ["Search results for: '#{search}'"] = "Suchergebnisse für: '#{search}'"; ["Search term (only complete words)"] = "Suchbegriff(e) (nur ganze Wörter)"; -["Select language"] = "Sprache wählen"; +["Select a notification level"] = "Ein Meldestufe für Benachrichtigungen auswählen"; ["Select language \"#{langcode}\""] = "Sprache \"#{langcode}\" wählen"; ["Send invite?"] = "Einladung schicken?"; +["Separate each paragraph with at least one blank line"] = "Jeden Absatz mit zumindest einer Leerzeile vom nächsten trennen"; ["Set URL"] = "URL setzen"; -["Set delegation for Area '#{name}'"] = "Delegation für Themenbereich '#{name}' festlegen"; -["Set delegation for Issue ##{number} in Area '#{area_name}'"] = "Delegation für Thema ##{number} im Themenbereich '#{area_name}' festlegen"; -["Set global delegation"] = "Globale Delegation festlegen"; -["Set new password"] = "Neues Kennwort setzen"; +["Set area delegation"] = "Themenbereich delegieren"; +["Set issue delegation"] = "Thema delegieren"; ["Set unit delegation"] = "Delegation für Gliederung setzen"; ["Settings"] = "Einstellungen"; +["Should the initiator implement this suggestion?"] = "Soll der Initiator diese Anregung umsetzen?"; ["Show"] = "Zeige"; +["Show all members"] = "Alle Mitglieder anzeigen"; ["Show areas in use"] = "Zeige verwendete Themenbereiche"; ["Show areas not in use"] = "Zeige nicht verwendete Themenbereiche"; -["Show diff"] = "Änderungen anzeigen"; -["Show filter details"] = "Zeige Filter-Details"; +["Show full history"] = "Komlette Historie anzeigen"; +["Show full member list"] = "Komplette Mitgliederliste anzeigen"; ["Show help text"] = "Zeige Hilfe-Text"; ["Show inactive units"] = "Zeige deaktivierte Gliederungen"; +["Show less"] = "Weniger anzeigen"; ["Show member"] = "Mitglied anzeigen"; -["Show member history"] = "Historie des Mitglieds anzeigen"; +["Show more and rate this"] = "Mehr zeigen und bewerten"; +["Show my voting ballot"] = "Meinen Stimmzettel anzeigen"; ["Show older events"] = "Zeige ältere Ereignisse"; -["Show only events which match... (or associtated)"] = "Zeige nur Ereignisse welche folgendes erfüllen... (oder-verknüpft)"; ["Show policies in use"] = "Zeige Regelwerke in Verwendung"; ["Show policies not in use"] = "Zeige deaktivierte Regelwerke"; ["Show profile"] = "Profil anzeigen"; +["Show voting ballot"] = "Stimmzettel anzeigen"; ["So I'm"] = "Also bin ich"; -["Software"] = "Software"; ["Sorry, but there is not confirmed email address for your account. Please contact the administrator or support."] = "Sorry, aber für diesen Account ist keine bestätigte E-Mail-Adresse hinterlegt. Bitte wende Dich an den Administrator oder den Support."; ["Sorry, but you are currently not invited"] = "Sorry, aber Du bist zur Zeit nicht eingeladen"; ["Sorry, you have reached your personal flood limit. Please be slower..."] = "Sorry, Du hast Dein persönliches Flood-Limit erreicht. Bitte sei langsamer..."; ["Sorry, your contingent for creating initiatives has been used up. Please try again later."] = "Sorry, Dein Antragskontingent ist zur Zeit ausgeschöpft. Bitte versuche es später erneut!"; ["Source"] = "Quelltext"; ["Standard policies"] = "Standardverfahren"; -["Start search"] = "Suche starten"; ["Statement"] = "Statement"; ["Status"] = "Status"; ["Status quo: #{rank}"] = "Status quo: #{rank}"; -["Stop ignoring member"] = "nicht mehr ignorieren"; ["Strict direct majority"] = "Strenge direkte Mehrheit"; ["Strict indirect majority"] = "Strenge indirekte Mehrheit"; -["Stylesheet URL"] = "Stylesheet URL"; +["Structured discussion"] = "Strukturierte Diskussion"; ["Stylesheet URL has been updated"] = "Stylesheet URL wurde aktualisiert"; +["Subject area subscribed"] = "für Themenbereich angemeldet"; +["Subject areas"] = "Themenbereiche"; +["Subscribed members (#{count})"] = "Angemeldete Teilnehmer (#{count})"; +["Subscription already removed"] = "bereits abgemeldet"; +["Subscription removed"] = "vom Themenbereich erfolgreich abgemeldet"; ["Suggest no initiative"] = "Keine Initiative empfehlen"; -["Suggested initiative"] = "Empfohlene Initiative"; ["Suggestion"] = "Anregung"; ["Suggestion ##{id}"] = "Anregung ##{id}"; ["Suggestion currently implemented"] = "Anregung zur Zeit umgesetzt"; @@ -577,86 +610,74 @@ ["Suggestion does not exist anymore"] = "Anregung existiert nicht mehr"; ["Suggestion for initiative: '#{name}'"] = "Anregung für Initiative '#{name}'"; ["Suggestions"] = "Anregungen"; -["Sunday"] = "Sonntag"; +["Suggestions for improvement (#{count})"] = "Verbesserungsvorschläge (#{count})"; ["Support this initiative"] = "Diese Initiative unterstützen"; -["Supported"] = "Unterstützt"; -["Supporters"] = "Unterstützer"; -["Supporters (before begin of voting)"] = "Unterstützer (zum Abstimmungesbeginn)"; ["Syntax help"] = "Syntax-Hilfe"; +["System administration"] = "Systemadministration"; +["System settings"] = "Systemeinstellungen"; +["Take a look through the existing issues. Maybe someone else started a debate on your topic (and you can join it) or the topic has been decided already in the past."] = "Schau dir die bestehenden Themen an. Vielleicht hat schon jemand eine Debatte über dein Thema gestartet (und du kannst daran teilnehmen) oder über das Thema wurde bereits in der Vergangenheit entschieden."; +["Tell others about this initiative:"] = "Anderen von dieser Initiative berichten:"; ["Terms of use"] = "Nutzungsbedingungen"; ["The code you've entered is invalid"] = "Der Code, den Du eingeben hast, ist nicht gültig!"; ["The draft of this initiative has been updated!"] = "Der Entwurfstext der Initiative wurde aktualisiert!"; ["The drafts do not differ"] = "Die Entwürfe unterscheiden sich nicht"; +["The initiative draft has been updated again in the meanwhile, support not updated!"] = "Der Entwurfstext der Initiative wurde zwischenzeitlich erneut geändert, die Unterstützung wurde daher nicht aktualisiert!"; +["The initiative text has been updated"] = "Der Entwurfstext der Initiative wurde geändert"; ["The initiators suggest to support the following initiative:"] = "Die Initiatoren empfehlen folgende Initiative zu unterstützen:"; +["The title is the figurehead of your iniative. It should be short but meaningful! As others identifies your initiative by this title, you cannot change it later!"] = "Der Titel ist das Aushängeschild einer Initiative. Er sollte bedeutungsvoll sein! Da die Initiative durch den Titel identifiziert wird, kann er später nicht mehr geändert werden!"; +["This delegation is suspended, because you voted yourself."] = "Die Delegation wurde durch eigenes Abstimmen ausgesetzt."; ["This email address is too short!"] = "Diese E-Mail-Adresse ist zu kurz!"; ["This initiative"] = "Diese Initiative"; -["This initiative has been revoked at #{revoked}"] = "Diese Initiative wurde am/um #{revoked} zurückgezogen"; -["This initiative has not been admitted! It failed the quorum of #{quorum}."] = "Diese Initiative wurde nicht zugelassen. Sie hat das Quorum von #{quorum} nicht erreicht."; +["This initiative has been revoked at #{revoked} by:"] = "Diese Initiative wurde am/um #{revoked} zurückgezogen, von:"; +["This initiative has not been admitted! It failed the 2nd quorum of #{quorum}."] = "Diese Initiative wurde nicht zugelassen! Sie ist am 2. Quorum (#{quorum}) gescheitert."; ["This initiative is already revoked"] = "Diese Initiative ist schon zurückgezogen"; ["This initiative is revoked"] = "Diese Initiative wurde zurückgezogen"; ["This invite key is connected with the following information:"] = "Dieser Einladungscode ist mit den folgenden Daten verknüpft:"; -["This issue has been canceled by administrative intervention."] = "Dieses Thema wurde durch administrativen Eingriff abgebrochen."; -["This issue has been canceled."] = "Dieses Thema wurde abgebrochen"; -["This issue has been canceled. It failed the quorum of #{quorum}."] = "Dieses Thema wurde abgebrochen. Es hat das Quorum von #{quorum} nicht erfüllt."; +["This is the only initiative in this issue, because nobody started a competing initiative."] = "Dies ist die einzige Initiative in diesem Thema, da niemand eine konkurrierende Initiative gestartet hat."; ["This issue is already closed."] = "Das Thema ist schon geschlossen."; ["This issue is already frozen."] = "Das Thema ist schon eingefroren"; +["This issue is closed"] = "Das Thema ist geschlossen"; ["This login is already taken, please choose another one!"] = "Dieser Anmeldename ist bereits vergeben, bitte wähle einen anderen!"; ["This login is too short!"] = "Dieser Anmeldename ist zu kurz!"; ["This member account has been created at #{created}"] = "Dieser Mitgliedszugang wurde am/um #{created} angelegt."; ["This member has rejected to become initiator of this initiative"] = "Dieses Mitglied hat die Einladung, Initiator zu werden, abgelehnt"; ["This member is already initiator of this initiative"] = "Dieses Mitglied ist bereits Initiator dieser Initiative"; ["This member is already invited to become initiator of this initiative"] = "Dieses Mitglied ist bereits eingeladen Initiator dieser Initiative zu werden"; +["This member is currently participating in this issue."] = "Dieses Mitglied nimmt zur Zeit an diesem Thema teil."; ["This member is inactive"] = "Mitglied ist inaktiv"; -["This member is initiator of this initiative"] = "Dieses Mitglied ist Initiator dieser Initiative"; ["This member is locked"] = "Mitglied ist gesperrt"; -["This member is participating, the rest of delegation chain is suspended while discussing"] = "Dieses Mitglied partizipiert, Rest der Delegationskette während der Diskussion ausgesetzt."; -["This member is potential supporter of this initiative"] = "Dieses Mitglied ist potentieller Unterstützer dieser Initiative"; -["This member is potential supporter of this initiative via delegation"] = "Dieses Mitglied ist durch Delegation potentieller Unterstützer dieser Initiative"; -["This member is supporter of this initiative"] = "Dieses Mitglied ist Unterstützer dieser Initiative"; -["This member is supporter of this initiative via delegation"] = "Dieses Mitglied ist durch Delegation Unterstützer dieser Initiative"; +["This member is participating, the remaining delegation chain is suspended during discussing."] = "Diese Mitglied nimmt am Thema teil, daher sind die folgenden Delegationen während der Diskussion ausgesetzt."; ["This name is already taken, please choose another one!"] = "Dieser Name ist bereits vergeben, bitte wähle einen anderen!"; -["This name is really too short!"] = "Dieser Name ist wirklich zu kurz!"; ["This name is too short!"] = "Dieser Name ist zu kurz!"; ["This screen name is too short!"] = "Dieser Screen-Name ist zu kurz!"; ["This service is provided by:"] = "Diensteanbieter:"; ["This service is provided using the following software components:"] = "Dieser Dienst ist mit folgender Software realisiert worden:"; -["This site is using"] = "Diese Seite benutzt"; ["This suggestion has been meanwhile deleted"] = "Diese Anregung wurde zwischenzeitlich gelöscht"; ["This title is really too short!"] = "Dieser Titel ist wirklich zu kurz!"; -["Thursday"] = "Donnerstag"; -["Timeline"] = "Zeitachse"; +["This title is too long!"] = "Der Titel ist zu lang!"; ["Title"] = "Titel"; -["Title (80 chars max)"] = "Titel (max. 80 Zeichen)"; -["Title of initiative"] = "Titel der Initiative"; -["Today at #{time}"] = "Heute um #{time}"; -["Traditional wiki syntax"] = "Traditionelle Wiki-Syntax"; -["Trustee"] = "Bevollmächtigter"; +["To create a competing initiative see below."] = "Um eine konkurrierende Initiative zu starten siehe unten."; ["Trustee has no voting right in this unit"] = "Bevollmächtigter hat kein Stimmrecht in dieser Gliederung"; -["Tuesday"] = "Dienstag"; -["Unconfirmed address"] = "Unbestätigte E-Mail"; +["Underline main headlines with ==="] = "Haupt-Überschriften mit === unterstreichen"; +["Underline sub headlines with ---"] = "Unter-Überschriften mit --- unterstreichen"; ["Unit"] = "Gliederung"; -["Unit '#{name}'"] = "Gliederung '#{name}'"; ["Unit delegation"] = "Gliederungsdelegation"; ["Unit list"] = "Liste der Gliederungen"; -["Unit: '#{name}'"] = "Gliederung: '#{name}'"; -["Units"] = "Gliederungen"; -["Units and areas"] = "Gliederungen und Themengebiete"; ["Unknown author"] = "Unbekannter Autor"; -["Update voting comment"] = "Abstimmungskommentar ändern"; ["Updated drafts"] = "Neue Entwürfe"; ["Upload avatar/photo"] = "Avatar/Foto hochladen"; -["Upload images"] = "Bilder hochladen"; +["Use [Text](http://example.com/) for links"] = "[Text](http://example.com/) verwenden für Links"; ["Use terms"] = "Nutzungsbedingungen"; +["Verification"] = "Überprüfung"; +["Verification #{time_info}"] = false; ["Verification started"] = "Phase Eingefroren gestartet"; -["Verification starts soon"] = "Phase Eingefroren startet in Kürze"; ["Verification time"] = "Zeit für Eingefroren"; -["Version"] = "Version"; -["Vote now"] = "Jetzt abstimmen"; -["Voted"] = "Abgestimmt"; +["Vote delegation"] = "Stimmdelegation"; ["Voted no"] = "Mit Nein gestimmt"; ["Voted yes"] = "Mit Ja gestimmt"; ["Voters"] = "Abstimmende"; ["Voting"] = "Abstimmung"; +["Voting #{time_info}"] = false; ["Voting comment"] = "Abstimmungskommentar"; ["Voting comment (last updated: #{timestamp})"] = "Abstimmmungskommentar (Letzte Änderung: #{timestamp})"; ["Voting comment (optional)"] = "Abstimmmungskommentar (optional)"; @@ -664,75 +685,87 @@ ["Voting for this issue has already begun."] = "Die Abstimmung für dieses Thema hat schon begonnen."; ["Voting has not started yet."] = "Die Abstimmung hat noch nicht begonnen."; ["Voting started"] = "Abstimmung begonnen"; -["Voting starts soon"] = "Abstimmung beginnt in Kürze"; ["Voting time"] = "Zeit für die Abstimmung"; ["We couldn't deliver a confirmation mail to this address. Please check entered email address."] = "Wir konnten keine Bestätigungs-E-Mail versenden. Bitte überprüfe die E-Mail-Adresse."; ["We have sent an email with activation link already in the last hour. Please try again later."] = "Wir haben bereits innerhalb der letzten Stunde eine E-Mail mit Bestätigungslink gesendet. Bitte versuche es später erneut."; ["Website"] = "Webseite"; -["Wednesday"] = "Mittwoch"; +["What can I do here?"] = "Was kann ich hier machen?"; +["What this member is currently supporting"] = "Was dieses Mitglied zur Zeit unterstützt"; ["Wiki engine"] = "Wiki engine"; ["Wiki engine for statement"] = "Wiki engine für das Statement"; ["Withdraw"] = "Zurückziehen"; ["Withdraw membership"] = "Mitgliedschaft aufgeben"; ["Yes"] = "Ja"; -["Yesterday at #{time}"] = "Gestern um #{time}"; +["Yes, it's implemented"] = "Ja, ist umgesetzt"; ["You already voted this issue"] = "Du hast dieses Thema bereits abgestimmt"; ["You are already initiator"] = "Du bist bereits Initiator"; -["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 currently not invited to any initiative."] = "Du bist zur Zeit von keiner Initiative eingeladen."; ["You are currently not supporting this initiative directly. By adding suggestions to this initiative you will automatically become a potential supporter."] = "Du bist zur Zeit kein direkter Unterstützer dieser Initiative. Wenn Du eine Anregung hinzufügst wirst Du automatisch potentieller Unterstützer!"; ["You are initiator of this initiative"] = "Du bist Initiator dieser Initiative"; -["You are interested"] = "Du bist interessiert"; ["You are interested in this issue"] = "Du bist an diesem Thema interessiert"; ["You are invited to #{count} initiative(s)"] = "Du bist zu #{count} Initiativen als Initiator eingeladen"; ["You are invited to LiquidFeedback. To register please click the following link:\n\n"] = "Du bist zu LiquidFeedback eingeladen. Bitte klicke auf den folgenden Link, um dich zu registrieren:\n\n"; -["You are invited to become initiator of this initiative."] = "Du bist eingeladen Initiator dieser Initiative zu werden."; +["You are invited to become initiator of '#{initiative_name}'"] = "Einladung Initiator der Initiative '#{initiative_name}' zu werden"; +["You are invited to become initiator of this initiative"] = "Du bist eingeladen Initiator dieser Initiative zu werden"; ["You are member"] = "Du bist Mitglied"; +["You are not eligible to participate"] = "Du bist nicht teilnahmeberechtigt"; +["You are not entitled to vote in this unit"] = "Du bist in dieser Gliederung nicht stimmberechtigt"; ["You are not participating in any of the #{count} areas in this unit"] = "Du nimmst an keinem der #{count} Themenbereiche dieser Gliederung teil"; ["You are not participating in the only area of the unit"] = "Du nimmst am einzigen Themenbereich der Gliederung nicht teil"; ["You are now initiator of this initiative"] = "Du bist jetzt Initiator dieser Initiative"; -["You are participating in this area"] = "Du bist Teilnehmer im Themengebiet"; ["You are potential supporter"] = "Du bist potentieller Unterstützer"; -["You are potential supporter of this initiative"] = "Du bist potentieller Unterstützer der Initiative"; -["You are potential supporter of this initiative via delegation"] = "Du bist durch Delegation potentieller Unterstützer der Initiative"; +["You are subscribed for this subject area"] = "Du bist für diesen Themenbereich angemeldet"; ["You are supporter"] = "Du bist Unterstützer"; -["You are supporter of this initiative"] = "Du bist Unterstützer dieser Initiative"; -["You are supporter of this initiative via delegation"] = "Du bist durch Delegation Unterstützer dieser Initiative"; +["You are supporting this initiative"] = "Du unterstützt diese Initiative"; +["You blocked this member (i.e. you will not be notified about this members actions)"] = "Du hast dieses Mitglied geblockt (d.h. du wirst nicht mehr über dessen Aktivitäten informiert)"; ["You can change your email address only once per hour. Please try again later."] = "Du kannst die E-Mail-Adresse nur einmal in der Stunde ändern, bitte versuche es später erneut."; +["You can change your text again anytime during admission and discussion phase"] = "Du kannst den Text während der Zulassungs- und Diskussionsphase jederzeit wieder ändern"; +["You can choose only members which you have been saved as contact before."] = "Du kannst nur Mitglieder ausählen, die du zuvor als Kontakt gespeichert hast."; ["You can't suggest the initiative you are revoking"] = "Du kannst nicht die Initiative empfehlen, die Du löschen möchtest"; +["You cannot change your text again later, because this issue is already in verfication phase!"] = "Du kannst den Text später nicht mehr ändern, da das Thema bereits in der Überprüfungsphase ist!"; +["You delegated this issue"] = "Du hast dieses Thema delegiert"; +["You delegated this organizational unit"] = "Du hast diese Gliederung delegiert"; +["You delegated this subject area"] = "Du hast diesen Themenbereich delegiert"; +["You delegated this unit"] = "Du hast diese Gliederung delegiert"; ["You didn't confirm your email address '#{email}' within 7 days."] = "Du hast die E-Mail-Adresse '#{email}' nicht innerhalb von 7 Tagen bestätigt."; ["You didn't confirm your email address '#{email}'. You have received an email with an activation link."] = "Du hast die E-Mail-Adresse '#{email}' nicht bestätigt. Du hast hierzu eine E-Mail mit einem Aktivierungslink erhalten."; ["You didn't save any member as contact yet."] = "Du hast noch kein Mitglied als Kontakt gespeichert!"; ["You didn't set the level of notifications you like to receive"] = "Du hast noch nicht ausgewählt, ob und welche Benachrichtigungen du erhalten möchtest."; -["You have ignored this member"] = "Du ignorierst dieses Mitglied"; +["You do not like to vote this issue (yourself)"] = "Du möchtest für dieses Thema nicht (selber) abstimmen"; +["You have been voted"] = "Du hast abgestimmt"; ["You have not voted #{count} issue(s) you were interested in"] = "Du hast für #{count} Themen, die dich interessieren, noch nicht abgestimmt"; ["You have to mark 'Are you sure' to revoke!"] = "Zum Zurückziehen musst Du 'Sicher?' auswählen"; -["You have voting privileges for this unit"] = "Du hast Stimmrecht in dieser Gliederung"; -["You need to be logged in, to use all features of this system."] = "Du musst eingeloggt sein, um alle Funktionen dieses Systems nutzen zu können."; -["You were interested"] = "Du warst interessiert"; +["You have voted"] = "Du hast abgestimmt"; +["You have voted via delegation"] = "Du hast per Delegation abgestimmt"; +["You may choose one of the ongoing initiatives you are currently supporting"] = "Du kannst eine der noch laufenden Initiativen auswählen, die du direkt unterstützt."; +["You refused to become initiator of this initiative"] = "Du hast abgelehnt Initiator dieser Initiative zu werden"; +["You saved this member as contact (i.e. to use as delegatee)"] = "Du hast dieses Mitglied gespeichert (z.B. um es als Delegierten zu verwenden)"; +["You saved this member as contact (i.e. to use as delegatee) and others can see it"] = "Du hast dieses Mitglied gespeichert (z.B. um es als Delegierten zu verwenden) und andere können das sehen"; ["You were potential supporter"] = "Du bist potentieller Unterstützer"; ["You were supporter"] = "Du bist Unterstützer"; ["You've successfully registered and you can login now with your login and password!"] = "Du hast Dich erfolgreich registriert und kannst Dich jetzt mit Deinen Anmeldenamen und Kennwort anmelden!"; +["Your avatar is a small photo, which will be shown always next to your name."] = "Dein Avatar ist ein kleines Bild, das überall neben deinem Namen angezeigt wird."; +["Your choice"] = "Deine Auswahl"; ["Your email address has been changed, please check for confirmation email with activation link!"] = "Deine E-Mail-Adresse wurde geändert, du hast eine Bestätigungs-E-Mail mit Aktivierungslink erhalten."; ["Your login has been changed to '#{login}'"] = "Dein Anmeldename wurde auf '#{login}' geändert"; ["Your name has been changed"] = "Dein Name wurde geändert"; ["Your page has been updated"] = "Deine Seite wurde aktualisiert"; ["Your password has been updated successfully"] = "Das Kennwort wurde erfolgreich geändert"; +["Your photo will be shown in your profile."] = "Dein Foto wird deinem Profil angezeigt"; ["Your rating has been deleted"] = "Deine Bewertung wurde gelöscht"; ["Your rating has been updated"] = "Deine Bewertung wurde aktualisiert"; ["Your request has been processed."] = "Die Anfrage wurde bearbeitet."; ["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 Initiative entzogen"; ["Your support has been updated to the latest draft"] = "Deine Unterstützung wurde auf den neuesten Entwurf aktualisiert"; ["Your vote has been discarded. Delegation rules apply if set."] = "Deine Abstimmung wurde zurückgezogen. Delegationsregeln gelten sofern gesetzt."; ["Z-A"] = "Z-A"; ["[Name of Language]"] = "Deutsch"; ["[No voting privilege]"] = "[Kein Stimmrecht]"; ["[Registered members only]"] = "[nur für Registrierte]"; +["[calculating]"] = "[wird berechnet...]"; ["[event mail] URL: #{url}"] = " URL: #{url}"; -["[event mail] Area: #{name}"] = "Themengebiet: #{name}"; +["[event mail] Area: #{name}"] = "Themenbereich: #{name}"; ["[event mail] Unit: #{name}"] = " Gliederung: #{name}"; ["[event mail] Event: #{event}"] = " Ereignis: #{event}"; ["[event mail] Issue: ##{id}"] = " Thema: ##{id}"; @@ -741,15 +774,58 @@ ["[not displayed public]"] = "[nicht öffentlich]"; ["a bit unsatisfied"] = "etwas unzufrieden"; ["abandoned"] = "ausgesetzt"; +["accept invitation"] = "Einladung annehmen"; ["action"] = "Aktion"; +["activate account"] = "Konto aktivieren"; ["activated"] = "aktiviert"; +["add my interest"] = "Interesse anmelden"; +["add my support"] = "unterstützen"; +["add to my list of private contacts"] = "Zur meiner Kontaktliste hinzufügen"; +["add to my list of public contacts"] = "Zu meiner öffentlichen Kontaktliste hinzufügen"; +["add your support (see above) and rate or write new suggestions (and thereby restrict your support to certain conditions if necessary)"] = "Die Initiative untersützen (siehe oben) und Verbesserungsvorschläge bewerten oder machen (und dabei ggfs. die Unterstützung beschränken)"; +["all issues"] = "alle Themen"; +["allow invitation again"] = "Einladen wieder erlauben"; +["and"] = "und"; ["and #{count} more initiatives"] = "und #{count} weitere Initiativen"; -["and one more initiative"] = "und eine weitere Initiative"; -["area"] = "Themengebiet"; +["area"] = "Themenbereich"; ["at least #{count} approvals"] = "mindestens #{count} Zustimmungen"; ["at least #{count} approvals or abstentions"] = "mindestens #{count} Zustimmungen oder Enthaltungen"; -["change discussion URL"] = "Diskussions-URL ändern"; +["author"] = "Autor"; +["avatar/photo"] = "Avatar/Foto"; +["block this member"] = "Dieses Mitglied blocken"; +["browse through the competing initiatives"] = "durch die konkurrierenden Initiativen sehen"; +["but"] = "aber"; +["by default only those issues are shown, for which your are eligible to participate (change filters on top of the list)"] = "Standardmäßig werden nur die Themen angezeigt, für die du teilnahmeberechtigt bist, Filter können am Anfang der Liste angepasst werden"; +["cancel"] = "Abbrechen"; +["cancel issue"] = "Thema abbrechen"; +["cancel issue now"] = "Thema jetzt abbrechen"; +["cancel registration"] = "Registrierung abbrechen"; +["canceled"] = "abgebrochen"; +["change avatar/photo"] = "Avatar/Foto ändern"; +["change my vote"] = "Abstimmung ändern"; +["change vote"] = "Abstimmung ändern"; +["change your login"] = "Anmeldenamen ändern"; +["change your notification email address"] = "E-Mail-Adresse für Benachrichtigungen ändern"; +["change your password"] = "Kennwort ändern"; +["change your screen name"] = "Screen name ändern"; +["change/revoke area delegation"] = "Delegation für Themenbereich ändern/widerrufen"; +["change/revoke delegation"] = "Delegation ändern/widerrufen"; +["change/revoke delegation of organizational unit"] = "Delegation für Gliederung ändern/widerrufen"; +["change/revoke delegation of subject area"] = "Delegation für Themenbereich ändern/widerrufen"; +["change/revoke delegation only for this issue"] = "Delegation nur für dieses Thema ändern/widerrufen"; +["change/revoke delegation only for this subject area"] = "Delegation nur für diesen Themenbereich ändern/widerrufen"; +["change/revoke issue delegation"] = "Delegation für Thema ändern/widerrufen"; +["check your "] = "überprüfe die "; +["choose delegatee"] = "Delegierten auswählen"; +["choose issue delegatee"] = "Delegierten für Thema auswählen"; +["choose subject area delegatee"] = "Delegierten für Themenbereich auswählen"; +["collapse subject areas"] = "Themenbereiche einklappen"; +["collective rating:"] = "kollektive Bewertung:"; +["compare"] = "vergleichen"; +["compare revisions"] = "Revisionen vergleichen"; ["confirm"] = "bestätigen"; +["confirmed address"] = "bestätigte Adresse"; +["database download"] = "Datenbank herunterladen"; ["day [interval ago]"] = "Tag"; ["day [interval time left]"] = "Tag"; ["day [interval]"] = "Tag"; @@ -759,15 +835,47 @@ ["deactivated"] = "deaktiviert"; ["delegated to"] = "delegiert an"; ["delegates to"] = "delegiert an"; +["delegation suspended during discussion"] = "Delegation während der Diskussion ausgesetzt"; ["delete

"] = "löschen

"; -["disabled"] = "ausgeschaltet"; +["developer settings"] = "Einstellungen für Entwickler"; +["direct interest"] = "direktes Interesse"; +["discard"] = "verwerfen"; +["discard my vote"] = "Meine Stimme widerrufen"; +["do not notify me about this voting anymore"] = "über diese Abstimmung nicht mehr benachrichtigen"; +["draft ID"] = "Entwurf ID"; +["draft history (#{count})"] = "Entwurfshistorie (#{count})"; +["edit profile data"] = "Profildaten bearbeiten"; +["edit proposal and/or reasons"] = "Antrag und/oder Begründung bearbeiten"; ["email"] = "E-Mail"; +["ends in #{state_time_left}"] = "endet in #{state_time_left}"; +["ends soon"] = "endet bald"; +["failed #{quorum}"] = "#{quorum} nicht erreicht"; +["finished"] = "abgeschlossen"; ["global"] = "Global"; +["hide details"] = "Details ausblenden"; ["i#{id}: #{name}"] = false; +["if you like to implement a suggestion in your proposal and/or reasons, update your initiative draft"] = "um einen Verbesserungsvorschlag umzusetzen, den Entwurfstext der Initiative aktualisieren"; ["implemented"] = "umgesetzt"; +["implemented:"] = "umgesetzt:"; +["in all phases"] = "in allen Phasen"; +["in my areas"] = "in meinen Themenbereichen"; +["in my units"] = "in meinen Gliederungen"; ["inactive"] = "inaktiv"; -["last 24 hours"] = "letzte 24 Stunden"; +["initiated by me"] = "von mir initiiert"; +["interest via delegation"] = "Interesse per Delegation"; +["interested directly or via delegation"] = "Interesse per Delegation oder direkt"; +["invite another initiator"] = "weiteren Initiator einladen"; +["is implemented"] = "ist umgesetzt"; +["is not implemented"] = "ist nicht umgesetzt"; +["issue"] = "Thema"; +["issue view"] = "Themenansicht"; ["login name"] = "Anmeldename"; +["login to participate"] = "anmelden um teilzunehmen"; +["logout"] = "abmelden"; +["make this contact private"] = "diesen Kontakt nicht mehr öffentlich zeigen"; +["make this contact public"] = "diesen Kontakt öffentlich zeigen"; +["member"] = "Mitglied"; +["member inactive"] = "Mitglied inaktiv"; ["month [interval ago]"] = "Monat"; ["month [interval time left]"] = "Monat"; ["month [interval]"] = "Monat"; @@ -776,28 +884,102 @@ ["months [interval]"] = "Monate"; ["more unsatisfied"] = "sehr unzufrieden"; ["must"] = "muss"; +["must be implemented"] = "muß umgesetzt werden"; ["must not"] = "darf nicht"; +["my issues"] = "meine Themen"; ["neutral"] = "neutral"; ["no reverse beat path to status quo (including ties)"] = "Kein rückwärtsgerichteter Schlagpfad zum Status Quo (Gleichstände eingeschlossen)"; ["none"] = "kein"; +["not admitted"] = "nicht zugelassen"; ["not implemented"] = "nicht umgesetzt"; +["not voted by me"] = "nicht von mir abgestimmt"; ["not yet"] = "bis jetzt nicht"; +["notification settings"] = "Benachrichtigungseinstellungen"; +["notifications"] = "Benachrichtigungen"; +["notifications settings"] = "Benachrichtigungseinstellungen"; +["one step back"] = "einen Schritt zurück"; +["open the appropriate subject area for your issue and follow the instruction on that page."] = "öffne das passende Themenbereich für dein Thema und folge dort den Anweisungen"; +["open the organizational unit, subject area or issue you like to delegate and follow the instruction on that page."] = "öffne die Gliederung, den Themenbereich oder das Thema, das du delegieren möchtest und folge dort den Anweisungen"; +["or swipe"] = "oder swipen"; +["phase ends soon"] = "Phase endet bald"; ["possibly instable result caused by multistage majority"] = "Möglicherweise instabiles Ergebnis aufgrund mehrstufiger Mehrheiten"; +["preference voting"] = "Präferenzabstimmung"; +["proceed with registration"] = "Registrierung fortsetzen"; ["prohibit potentially instable results caused by multistage majorities"] = "Instabile Ergebnisse aufgrund mehrstufiger Mehrheiten verbieten"; +["public administrative notice:"] = "Öffentlicher administrativer Kommentar"; +["publish avatar/photo"] = "Avatar/Foto veröffentlichen"; +["publish my rating"] = "Wertung veröffentlichen"; +["publish profile data"] = "Profildaten veröffentlichen"; +["publish suggestion"] = "Verbesserungsvorschlag veröffentlichen"; +["published at"] = "veröffentlicht am/um"; +["reached #{quorum}"] = "#{quorum} erreicht"; +["refresh my support"] = "meine Unterstützung erneuern"; +["refuse invitation"] = "Einladung ablehnen"; +["remove an initiator"] = "Initiator entfernen"; +["remove from my contact list"] = "aus meiner Kontaktliste entfernen"; +["remove my interest"] = "Interesse abmelden"; +["remove my support"] = "Unterstützung widerrufen"; ["reverse beat path to status quo (including ties)"] = "Rückwärtsgerichteter Schlagpfad zum Status Quo (Gleichstände eingeschlossen)"; ["revoke"] = "zurückziehen"; +["revoke initiative"] = "Initiative zurückziehen"; +["revoked"] = "zurückgezogen"; ["satisfied"] = "zufrieden"; +["search"] = "suchen"; +["select tabs"] = "Andere Tabs auswählen"; ["should"] = "soll"; +["should be implemented"] = "soll umgesetzt werden"; ["should not"] = "soll nicht"; +["show all units"] = "Alle Gliederungen anzeigen"; +["show details"] = "Details anzeigen"; +["show differences"] = "Unterschiede anzeigen"; +["show other subject areas"] = "andere Themenbereiche anzeigen"; +["show saved contacts"] = "Gespeicherte Kontakte anzeigen"; +["show subject areas"] = "Themenbereiche anzeigen"; +["show vote"] = "Stimmzettel anzeigen"; +["start a new competing initiative"] = "eine neue konkurrierende Initiative starten"; +["start an initiative in a new issue"] = "eine Initiative in einem neuen Thema starten"; +["structured discussion"] = "strukturierte Diskussion"; +["subscribe"] = "Interesse anmelden"; +["subscribe subject areas or add your interested to issues and you will be notified about changes (follow the instruction on the area or issue page)"] = "Melde dich für Themenbereiche an oder interessiere dich für Themen, damit du benachrichtigst wird (folge den Anweisungen auf der Themenbereichs- bzw. Themenseite)"; +["subscribed"] = "am Themenbereich angemeldet"; +["suggestions (#{count}) ↓"] = "Verbesserungsvorschläge (#{count}) ↓"; +["supporter"] = "Unterstützer"; +["supporter with restricting suggestions"] = "Unterstützer mit beschränkenden Verbesserungsvorschlägen"; +["take a look at the competing initiatives"] = "schau dir die konkurrierenden Initiativen an"; +["take a look at the suggestions (see left) and rate them"] = "schau dir die Anregungen (links) an und bewerte sie"; +["take a look at the suggestions of your supporters"] = "schau die die Anregungen deiner Unterstützer an"; +["take a look on the issues (see left)"] = "schau dir die Themen an (siehe links)"; ["the following login is connected to this email address:\n\n"] = "der folgende Anmeldename ist mit dieser E-Mail-Adresse verknüpft:\n\n"; +["this issue is in verification phase, therefore the initiative text cannot be updated anymore"] = "dieses Thema ist in der Überprüfungsphase, daher kann der Text nicht mehr geändert werden"; +["this issue is in voting phase, therefore the initiative text cannot be updated anymore"] = "dieses Thema ist in Abstimmung, daher kann der Text nicht mehr geändert werden"; +["timeline"] = "Zeitlicher Verlauf"; +["to argue about suggestions, just add your arguments to your reasons in the initiative draft, so your supporters can learn about your opinion"] = "um Verbesserungsvorschlägen zu kommentieren, füge deine Argumente in den Text deiner Initiative ein, damit deine Untersützer deine Position verstehen können"; ["to reset your password please click on the following link:\n\n"] = "um Dein Kennwort zurückzusetzen klicke bitte den folgenden Link an:\n\n"; +["to show more info and learn what you can do"] = "für mehr Infos und 'Was kann ich tun?'"; +["today at #{time}"] = "heute um #{time}"; +["unblock member"] = "Blockierung aufheben"; +["unconfirmed address"] = "unbestätigte Adresse"; ["unit"] = "Gliederung"; -["unit / area"] = "Gliederung / Themengebiet"; +["unit / area"] = "Gliederung / Themenbereich"; +["unsubscribe"] = "Interesse abmelden"; ["until"] = "bis"; +["update area"] = "Themenbereich aktualisiern"; +["update member"] = "Mitglied aktualisieren"; +["update policy"] = "Regelwerk aktualisieren"; +["update unit"] = "Gliederung aktualisieren"; ["variable"] = "variabel"; -["with winner"] = "mit Gewinner"; +["via delegation"] = "per Delegation"; +["vote delegation"] = "Stimmdelegation"; +["vote now"] = "jetzt abstimmen"; +["voted and not voted by me"] = "von mir abgestimmt und nicht abgestimmt"; +["voted by me"] = "von mir abgestimmt"; +["voted directly by me"] = "von mir direkt abgestimmt"; +["voted no"] = "mit Nein gestimmt"; +["voted via delegation"] = "von mir per Delegation abgestimmt"; +["voted yes"] = "mit Ja gestimmt"; ["without"] = "ohne"; -["without winner"] = "ohne Gewinner"; +["write a new suggestion"] = "neuen Verbesserungsvorschlag einbringen"; +["written and rated by the supportes of this initiative to improve the proposal and its reasons"] = "geschrieben und bewertet von Unterstützern dieser Initiative"; ["xmpp"] = "Jabber (XMPP)"; ["year [interval ago]"] = "Jahr"; ["year [interval time left]"] = "Jahr"; @@ -805,4 +987,10 @@ ["years [interval ago]"] = "Jahren"; ["years [interval time left]"] = "Jahre"; ["years [interval]"] = "Jahre"; +["yesterday at #{time}"] = "gestern um #{time}"; +["you are interested"] = "du bist interessiert"; +["you are subscribed"] = "du bist am Themembreich angemeldet"; +["you have #{count} incoming delegations"] = "#{count} eingehende Delegationen"; +["you restricted your support by rating suggestions as must or must not"] = "deine Untersützung ist aufgrund von 'muss'- oder 'darf nicht'-Anregungen beschränkt"; +["you voted"] = "du hast abgestimmt"; } diff -r a6c7bf07badb -r 701a5cf6b067 model/battle.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/model/battle.lua Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,10 @@ +Battle = mondelefant.new_class() +Battle.table = 'battle' + +function Battle:getByInitiativeIds(winning_id, losing_id) + local selector = Battle:new_selector() + selector:add_where { "winning_initiative_id = ?", winning_id } + selector:add_where { "losing_initiative_id = ?", losing_id } + selector:optional_object_mode() + return selector:exec() +end diff -r a6c7bf07badb -r 701a5cf6b067 model/contact.lua --- a/model/contact.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/model/contact.lua Thu Jul 10 01:19:48 2014 +0200 @@ -33,6 +33,9 @@ if args.member_id then selector:add_where{ "member_id = ?", args.member_id } end + if args.public ~= nil then + selector:add_where{ "public = ?", args.public } + end if args.order then if args.order == "name" then selector:add_order_by("member.name") diff -r a6c7bf07badb -r 701a5cf6b067 model/initiative.lua --- a/model/initiative.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/model/initiative.lua Thu Jul 10 01:19:48 2014 +0200 @@ -10,6 +10,14 @@ } Initiative:add_reference{ + mode = 'm1', + to = "Member", + this_key = 'revoked_by_member_id', + that_key = 'id', + ref = 'revoked_by_member', +} + +Initiative:add_reference{ mode = '1m', to = "Draft", this_key = 'id', @@ -26,6 +34,7 @@ that_key = 'initiative_id', ref = 'suggestions', back_ref = 'initiative', + default_order = '"proportional_order" NULLS LAST, id' } Initiative:add_reference{ @@ -223,6 +232,61 @@ :add_where("initiative.revoked ISNULL") end +function Initiative:getSpecialSelector( args ) + local selector = Initiative:new_selector() + selector:join( "issue", nil, "issue.id = initiative.issue_id" ) + selector:join( "area", nil, "area.id = issue.area_id" ) + if args.area_id then + selector:add_where{ "area.id = ?", args.area_id } + elseif args.unit_id then + selector:add_where{ "area.unit_id = ?", args.unit_id } + end + selector:limit( 1 ) + selector:optional_object_mode() + return selector +end + +function Initiative:getLastWinner( args ) + local selector = Initiative:getSpecialSelector( args ) + selector:add_where( "issue.state = 'finished_with_winner'" ) + selector:add_order_by( "issue.closed DESC, id DESC" ) + return selector:exec() +end + +function Initiative:getLastLoser( args ) + local selector = Initiative:getSpecialSelector( args ) + selector:add_where( "issue.state = 'finished_without_winner'" ) + selector:add_order_by( "issue.closed DESC, id DESC" ) + return selector:exec() +end + +function Initiative:getNextEndingVoting( args ) + local selector = Initiative:getSpecialSelector( args ) + selector:add_where( "issue.state = 'voting'" ) + selector:add_order_by( "issue.fully_frozen + issue.verification_time DESC, id DESC" ) + return selector:exec() +end + +function Initiative:getNextEndingVerification( args ) + local selector = Initiative:getSpecialSelector( args ) + selector:add_where( "issue.state = 'verification'" ) + selector:add_order_by( "issue.half_frozen + issue.verification_time DESC, id DESC" ) + return selector:exec() +end + +function Initiative:getNextEndingDiscussion( args ) + local selector = Initiative:getSpecialSelector( args ) + selector:add_where( "issue.state = 'discussion'" ) + selector:add_order_by( "issue.accepted + issue.discussion_time DESC, id DESC" ) + return selector:exec() +end + +function Initiative:getBestInAdmission( args ) + local selector = Initiative:getSpecialSelector( args ) + selector:add_where( "issue.state = 'admission'" ) + selector:add_order_by( "issue.created + issue.admission_time DESC, id DESC" ) + return selector:exec() +end function Initiative.object_get:current_draft() return Draft:new_selector() @@ -240,6 +304,10 @@ return name end +function Initiative.object_get:display_name() + return "i" .. self.id .. ": " .. self.name +end + function Initiative.object_get:initiator_names() local members = Member:new_selector() :join("initiator", nil, "initiator.member_id = member.id") @@ -254,3 +322,8 @@ return member_names end +function Initiative.object_get:potential_supporter_count() + if self.supporter_count and self.satisfied_supporter_count then + return self.supporter_count - self.satisfied_supporter_count + end +end diff -r a6c7bf07badb -r 701a5cf6b067 model/issue.lua --- a/model/issue.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/model/issue.lua Thu Jul 10 01:19:48 2014 +0200 @@ -142,23 +142,29 @@ if #ids == 0 then return sub_selector:empty_list_mode() end - sub_selector:from("issue") - sub_selector:add_field("issue.id", "issue_id") - sub_selector:add_field{ '(delegation_info(?, null, null, issue.id, ?)).*', options.member_id, options.trustee_id } - sub_selector:add_where{ 'issue.id IN ($)', ids } + sub_selector:from ( "issue" ) + sub_selector:add_field ( "issue.id", "issue_id" ) + sub_selector:add_field { '(delegation_info(?, null, null, issue.id, ?)).*', options.member_id, options.trustee_id } + sub_selector:add_where { 'issue.id IN ($)', ids } local selector = Issue:get_db_conn():new_selector() - selector:add_from("issue") - selector:join(sub_selector, "delegation_info", "delegation_info.issue_id = issue.id") - selector:left_join("member", "first_trustee", "first_trustee.id = delegation_info.first_trustee_id") - selector:left_join("member", "other_trustee", "other_trustee.id = delegation_info.other_trustee_id") - selector:add_field("delegation_info.*") - selector:add_field("first_trustee.name", "first_trustee_name") - selector:add_field("other_trustee.name", "other_trustee_name") - selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", options.member_id }) - selector:add_field("direct_voter.member_id NOTNULL", "direct_voted") - selector:left_join("non_voter", nil, { "non_voter.issue_id = issue.id AND non_voter.member_id = ?", options.member_id }) - selector:add_field("non_voter.member_id NOTNULL", "non_voter") + selector:add_from ( "issue" ) + selector:join(sub_selector, "delegation_info", "delegation_info.issue_id = issue.id" ) + selector:left_join ( "member", "first_trustee", "first_trustee.id = delegation_info.first_trustee_id" ) + selector:left_join ( "member", "other_trustee", "other_trustee.id = delegation_info.other_trustee_id" ) + selector:add_field ( "delegation_info.*" ) + selector:add_field ( "first_trustee.name", "first_trustee_name" ) + selector:add_field ( "other_trustee.name", "other_trustee_name" ) + selector:left_join ( "direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", options.member_id }) + selector:add_field ( "direct_voter.member_id NOTNULL", "direct_voted") + selector:left_join ( "non_voter", nil, { "non_voter.issue_id = issue.id AND non_voter.member_id = ?", options.member_id }) + selector:add_field ( "non_voter.member_id NOTNULL", "non_voter" ) + selector:left_join ( "direct_interest_snapshot", nil, { [[ + direct_interest_snapshot.issue_id = issue.id AND + direct_interest_snapshot.event = issue.latest_snapshot_event AND + direct_interest_snapshot.member_id = ? + ]], options.member_id }) + selector:add_field ( "direct_interest_snapshot.weight", "weight" ) return selector end } @@ -189,19 +195,19 @@ function Issue:get_state_name_for_state(value) local state_name_table = { - admission = _"New", + admission = _"Admission", discussion = _"Discussion", - verification = _"Frozen", + verification = _"Verification", voting = _"Voting", - canceled_revoked_before_accepted = _"Canceled (before accepted due to revocation)", - canceled_issue_not_accepted = _"Canceled (issue not accepted)", - canceled_after_revocation_during_discussion = _"Canceled (during discussion due to revocation)", - canceled_after_revocation_during_verification = _"Canceled (during verification due to revocation)", + canceled_revoked_before_accepted = _"Revoked (during admission)", + canceled_issue_not_accepted = _"Failed 1st quorum", + canceled_after_revocation_during_discussion = _"Revoked (during discussion)", + canceled_after_revocation_during_verification = _"Revoked (during verification)", canceled_by_admin = _"Canceled by administrative intervention", calculation = _"Calculation", - canceled_no_initiative_admitted = _"Canceled (no initiative admitted)", - finished_without_winner = _"Finished (without winner)", - finished_with_winner = _"Finished (with winner)", + canceled_no_initiative_admitted = _"All initiatives failed 2nd quorum", + finished_without_winner = _"Disapproved", + finished_with_winner = _"Finished with winner", } return state_name_table[value] or value or '' end @@ -275,3 +281,17 @@ function Issue.object_get:etherpad_url() return config.etherpad.base_url .. "p/" .. config.etherpad.group_id .. "$Issue" .. self.id end + +function Issue.object_get:name() + return self.policy.name .. " #" .. self.id +end + +function Issue.object_get:state_time_text() + if self.closed then + return _("#{closed_ago} ago", { closed_ago = self.closed_ago }) + elseif string.sub(self.state_time_left, 1, 2) ~= "-" then + return _("ends soon", { state_time_left = self.state_time_left }) + else + return _("ends in #{state_time_left}", { state_time_left = self.state_time_left }) + end +end diff -r a6c7bf07badb -r 701a5cf6b067 model/member.lua --- a/model/member.lua Thu Jul 10 01:02:43 2014 +0200 +++ b/model/member.lua Thu Jul 10 01:19:48 2014 +0200 @@ -124,7 +124,7 @@ that_key = 'truster_id', ref = 'outgoing_delegations', back_ref = 'truster', - default_order = '"id"' +-- default_order = '"id"' } Member:add_reference{ @@ -134,7 +134,7 @@ that_key = 'trustee_id', ref = 'incoming_delegations', back_ref = 'trustee', - default_order = '"id"' +-- default_order = '"id"' } Member:add_reference{ diff -r a6c7bf07badb -r 701a5cf6b067 static/back.png Binary file static/back.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/back50.png Binary file static/back50.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/16/chart_organisation.png Binary file static/icons/16/chart_organisation.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/empty.png Binary file static/icons/32/empty.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/phase_current.png Binary file static/icons/32/phase_current.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/phase_failed.png Binary file static/icons/32/phase_failed.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/phase_finished.png Binary file static/icons/32/phase_finished.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/support_none.png Binary file static/icons/32/support_none.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/support_satisfied.png Binary file static/icons/32/support_satisfied.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/support_satisfied_via_delegation.png Binary file static/icons/32/support_satisfied_via_delegation.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/support_unsatisfied.png Binary file static/icons/32/support_unsatisfied.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/support_unsatisfied_via_delegation.png Binary file static/icons/32/support_unsatisfied_via_delegation.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/32/voted_no.png Binary file static/icons/32/voted_no.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/bell.png Binary file static/icons/48/bell.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/eye.png Binary file static/icons/48/eye.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/home.png Binary file static/icons/48/home.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/info.png Binary file static/icons/48/info.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/lf_plus.png Binary file static/icons/48/lf_plus.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/star.png Binary file static/icons/48/star.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/star_empty.png Binary file static/icons/48/star_empty.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/icons/48/voted_ok.png Binary file static/icons/48/voted_ok.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/js/less-1.4.1.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/js/less-1.4.1.min.js Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,11 @@ +/* + * LESS - Leaner CSS v1.4.1 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache 2.0 License. + * + * @licence + */(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,i,s){e?k(e,i.href):t&&S(t.toCSS(r),i,s.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=b(t.href,e.location.href),u=o.url,a=l&&l.getItem(u),f=l&&l.getItem(u+":timestamp"),c={css:a,timestamp:f},h,p={relativeUrls:r.relativeUrls,currentDirectory:o.path,filename:u};t instanceof r.tree.parseEnv?(h=new r.tree.parseEnv(t),p.entryPath=h.currentFileInfo.entryPath,p.rootpath=h.currentFileInfo.rootpath,p.rootFilename=h.currentFileInfo.rootFilename):(h=new r.tree.parseEnv(r),h.mime=t.type,p.entryPath=o.path,p.rootpath=r.rootpath||o.path,p.rootFilename=u),h.relativeUrls&&(r.rootpath?p.rootpath=b(r.rootpath+y(o.path,p.entryPath)).path:p.rootpath=o.path),x(u,t.type,function(e,a){v+=e.replace(/@import .+?;/ig,"");if(!i&&c&&a&&(new Date(a)).valueOf()===(new Date(c.timestamp)).valueOf())S(c.css,t),n(null,null,e,t,{local:!0,remaining:s},u);else try{h.contents[u]=e,h.paths=[o.path],h.currentFileInfo=p,(new r.Parser(h)).parse(e,function(r,i){if(r)return n(r,null,null,t);try{n(r,i,e,t,{local:!1,lastModified:a,remaining:s},u),h.currentFileInfo.rootFilename===u&&N(document.getElementById("less-error-message:"+E(u)))}catch(r){n(r,null,null,t)}})}catch(f){n(f,null,null,t)}},function(e,r){n({type:"File",message:"'"+r+"' wasn't found ("+e+")"},null,null,t)})}function E(e){return e.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r=t.href||"",i="less:"+(t.title||E(r)),s=document.getElementById(i),o=!1,u=document.createElement("style");u.setAttribute("type","text/css"),t.media&&u.setAttribute("media",t.media),u.id=i;if(u.styleSheet)try{u.styleSheet.cssText=e}catch(a){throw new Error("Couldn't reassign styleSheet.cssText.")}else u.appendChild(document.createTextNode(e)),o=s!==null&&s.childNodes.length>0&&u.childNodes.length>0&&s.firstChild.nodeValue===u.firstChild.nodeValue;var f=document.getElementsByTagName("head")[0];if(s==null||o===!1){var c=t&&t.nextSibling||null;(c||document.getElementsByTagName("head")[0]).parentNode.insertBefore(u,c)}s&&o===!1&&f.removeChild(s);if(n&&l){C("saving "+r+" to cache.");try{l.setItem(r,e),l.setItem(r+":timestamp",n)}catch(a){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,n){var i="less-error-message:"+E(n||""),s='
  • {content}
  • ',o=document.createElement("div"),u,a,f=[],l=e.filename||n,c=l.match(/([^\/]+(\?.*)?)$/)[1];o.id=i,o.className="less-error-message",a="

    "+(e.type||"Syntax")+"Error: "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+c+" ";var h=function(e,n,r){e.extract[n]!=t&&f.push(s.replace(/\{line\}/,(parseInt(e.line)||0)+(n-1)).replace(/\{class\}/,r).replace(/\{content\}/,e.extract[n]))};e.extract?(h(e,0,""),h(e,1,"line"),h(e,2,""),a+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+f.join("")+"
    "):e.stack&&(a+="
    "+e.stack.split("\n").slice(1).join("
    ")),o.innerHTML=a,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),o.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(u=setInterval(function(){document.body&&(document.getElementById(i)?document.body.replaceChild(o,document.getElementById(i)):document.body.insertBefore(o,document.body.firstChild),clearInterval(u))},10))}var r,i,s;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof e=="undefined"?r={}:r=e.less={},i=r.tree={},r.mode="rhino"):typeof e=="undefined"?(r=exports,i=n("./tree"),r.mode="node"):(typeof e.less=="undefined"&&(e.less={}),r=e.less,i=e.less.tree={},r.mode="browser"),r.Parser=function(t){function m(){a=c[u],f=o,h=o}function g(){c[u]=a,o=f,h=o}function y(){o>h&&(c[u]=c[u].slice(o-h),h=o)}function b(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function w(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,y();else{y();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return E(r),typeof t=="string"?t:t.length===1?t[0]:t}function E(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function k(e,t,i){var s=i.currentFileInfo.filename;return r.mode!=="browser"&&r.mode!=="rhino"&&(s=n("path").resolve(s)),{lineNumber:C(e,t).line+1,fileName:s}}function L(e,t){var n=N(e,t),r=C(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.currentFileInfo.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&C(e.call,n).line+1,this.callExtract=o[C(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this;t instanceof i.parseEnv||(t=new i.parseEnv(t));var v=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n,i){var s=this;this.queue.push(e),r.Parser.importer(e,n,function(t,n,r){s.queue.splice(s.queue.indexOf(e),1);var o=r in s.files;s.files[r]=n,t&&!s.error&&(s.error=t),i(t,n,o)},t)}};return L.prototype=new Error,L.prototype.constructor=L,this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,p={imports:v,parse:function(e,a){var f,d,v,m,g,y,b=[],E,S=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.currentFileInfo.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(S)return a(new L(S,t));try{f=new i.Ruleset([],w(this.parsers.primary)),f.root=!0,f.firstRoot=!0}catch(x){return a(new L(x,t))}f.toCSS=function(e){var s,o,u;return function(s,o){s=s||{};var u,a=new i.evalEnv(s);typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),a.frames=[new i.Ruleset(null,o)]);try{var f=e.call(this,a);(new i.joinSelectorVisitor).run(f),(new i.processExtendsVisitor).run(f);var l=f.toCSS({compress:Boolean(s.compress),dumpLineNumbers:t.dumpLineNumbers,strictUnits:Boolean(s.strictUnits)})}catch(c){throw new L(c,t)}return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(l,s.maxLineLen):s.compress?l.replace(/(\s)+/g,"$1"):l}}(f.eval);if(o=0&&s.charAt(T)!=="\n";T--)N++;S={type:"Parse",message:"Unrecognised input",index:o,filename:t.currentFileInfo.filename,line:g,column:N,extract:[y[g-2],y[g-1],y[g]]}}var C=function(e){e=S||e||p.imports.error,e?(e instanceof L||(e=new L(e,t)),a(e)):a(null,f)};t.processImports!==!1?(new i.importVisitor(this.imports,C)).run(f):C()},parsers:{primary:function(){var e,t=[];while((e=w(this.extendRule)||w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/)||w(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(w(/^\/\/.*/),!0);if(e=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,n=o,r,u=o;s.charAt(n)==="~"&&(n++,r=!0);if(s.charAt(n)!=='"'&&s.charAt(n)!=="'")return;r&&w("~");if(e=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],r,u,t.currentFileInfo)},keyword:function(){var e;if(e=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=w(this.alpha);if(typeof s!="undefined")return s}w("("),r=w(this.entities.arguments);if(!w(")"))return;if(e)return new i.Call(e,r,a,t.currentFileInfo)},arguments:function(){var e=[],t;while(t=w(this.entities.assignment)||w(this.expression)){e.push(t);if(!w(","))break}return e},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)||w(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=w(/^\w+(?=\s?=)/i))&&w("=")&&(t=w(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!w(/^url\(/))return;return e=w(this.entities.quoted)||w(this.entities.variable)||w(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",S(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.currentFileInfo)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=w(/^@@?[\w-]+/)))return new i.Variable(e,n,t.currentFileInfo)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=w(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.currentFileInfo)},color:function(){var e;if(s.charAt(o)==="#"&&(e=w(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=w(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))return new i.Dimension(e[1],e[2])},unicodeDescriptor:function(){var e;if(e=w(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&w("~");if(e=w(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=w(/^(@[\w-]+)\s*:/)))return e[1]},extend:function(e){var t,n,r=o,s,u=[];if(!w(e?/^&:extend\(/:/^:extend\(/))return;do{s=null,t=[];for(;;){s=w(/^(all)(?=\s*(\)|,))/);if(s)break;n=w(this.element);if(!n)break;t.push(n)}s=s&&s[1],u.push(new i.Extend(new i.Selector(t),s,r))}while(w(","));return S(/^\)/),e&&S(/^;/),u},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var e=[],n,r,u,a,f,l=o,c=s.charAt(o),h=!1;if(c!=="."&&c!=="#")return;m();while(n=w(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=w(">");w("(")&&(u=this.mixin.args.call(this,!0).args,S(")")),u=u||[],w(this.important)&&(h=!0);if(e.length>0&&(w(";")||T("}")))return new i.mixin.Call(e,u,l,t.currentFileInfo,h);g()},args:function(e){var t=[],n=[],r,u=[],a,f,l,c,h,p={args:null,variadic:!1};for(;;){if(e)h=w(this.expression);else{w(this.comment);if(s.charAt(o)==="."&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({variadic:!0});break}h=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)}if(!h)break;l=null,h.throwAwayComments&&h.throwAwayComments(),c=h;var d=null;if(e){if(h.value.length==1)var d=h.value[0]}else d=h;if(d&&d instanceof i.Variable)if(w(":"))t.length>0&&(r&&x("Cannot mix ; and , as delimiter types"),a=!0),c=S(this.expression),l=f=d.name;else{if(!e&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({name:h.name,variadic:!0});break}e||(f=l=d.name,c=null)}c&&t.push(c),u.push({name:l,value:c});if(w(","))continue;if(w(";")||r)a&&x("Cannot mix ; and , as delimiter types"),r=!0,t.length>1&&(c=new i.Value(t)),n.push({name:f,value:c}),f=null,t=[],a=!1}return p.args=r?n:u,p},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||T(/^[^{]*\}/))return;m();if(n=w(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];var h=this.mixin.args.call(this,!1);t=h.args,c=h.variadic,w(")")||(l=o,g()),w(this.comment),w(/^when/)&&(f=S(this.conditions,"expected condition")),r=w(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);g()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||T("}")},alpha:function(){var e;if(!w(/^\(opacity=/i))return;if(e=w(/^\d+/)||w(this.entities.variable))return S(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=w(this.combinator),e=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||w("*")||w("&")||w(this.attribute)||w(/^\([^()@]+\)/)||w(/^[\.#](?=@)/)||w(this.entities.variableCurly),e||w("(")&&(r=w(this.selector))&&w(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e=s.charAt(o);if(e===">"||e==="+"||e==="~"||e==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(e)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u,a=[];while((u=w(this.extend))||(t=w(this.element))){u?a.push.apply(a,u):(a.length&&x("Extend can only be used at the end of selector"),r=s.charAt(o),n.push(t),t=null);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n,a);a.length&&x("Extend must be used to extend a selector, it cannot be used on its own")},attribute:function(){var e="",t,n,r;if(!w("["))return;(t=w(this.entities.variableCurly))||(t=S(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/));if(r=w(/^[|~*$^]?=/))n=w(this.entities.quoted)||w(/^[\w-]+/)||w(this.entities.variableCurly);return S("]"),new i.Attribute(t,r,n)},block:function(){var e;if(w("{")&&(e=w(this.primary))&&w("}"))return e},ruleset:function(){var e=[],n,r,u;m(),t.dumpLineNumbers&&(u=k(o,s,t));while(n=w(this.selector)){e.push(n),w(this.comment);if(!w(","))break;w(this.comment)}if(e.length>0&&(r=w(this.block))){var a=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(a.debugInfo=u),a}l=o,g()},rule:function(e){var n,r,u=s.charAt(o),a;m();if(u==="."||u==="#"||u==="&")return;if(n=w(this.variable)||w(this.property)){r=!e&&(t.compress||n.charAt(0)==="@")?w(this.value)||w(this.anonymousValue):w(this.anonymousValue)||w(this.value),a=w(this.important);if(r&&w(this.end))return new i.Rule(n,r,a,f,t.currentFileInfo);l=o,g();if(r&&!e)return this.rule(!0)}},anonymousValue:function(){var e;if(e=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))return o+=e[0].length-1,new i.Anonymous(e[1])},"import":function(){var e,n,r=o;m();var s=w(/^@import?\s+/),u=(s?w(this.importOptions):null)||{};if(s&&(e=w(this.entities.quoted)||w(this.entities.url))){n=w(this.mediaFeatures);if(w(";"))return n=n&&new i.Value(n),new i.Import(e,n,u,r,t.currentFileInfo)}g()},importOptions:function(){var e,t={},n,r;if(!w("("))return null;do if(e=w(this.importOption)){n=e,r=!0;switch(n){case"css":n="less",r=!1;break;case"once":n="multiple",r=!1}t[n]=r;if(!w(","))break}while(e);return S(")"),t},importOption:function(){var e=w(/^(less|css|multiple|once)/);if(e)return e[1]},mediaFeature:function(){var e,n,r=[];do if(e=w(this.entities.keyword))r.push(e);else if(w("(")){n=w(this.property),e=w(this.value);if(!w(")"))return null;if(n&&e)r.push(new i.Paren(new i.Rule(n,e,null,o,t.currentFileInfo,!0)));else{if(!e)return null;r.push(new i.Paren(e))}}while(e);if(r.length>0)return new i.Expression(r)},mediaFeatures:function(){var e,t=[];do if(e=w(this.mediaFeature)){t.push(e);if(!w(","))break}else if(e=w(this.entities.variable)){t.push(e);if(!w(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=k(o,s,t));if(w(/^@media/)){e=w(this.mediaFeatures);if(n=w(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=w(this["import"])||w(this.media))return n;m(),e=w(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(w(/^[^{]+/)||"").trim());if(c){if(r=w(this.block))return new i.Directive(e,r)}else if((n=p?w(this.expression):w(this.entity))&&w(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=k(o,s,t)),d}g()},value:function(){var e,t=[],n;while(e=w(this.expression)){t.push(e);if(!w(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return w(/^! *important/)},sub:function(){var e,t;if(w("("))if(e=w(this.addition))return t=new i.Expression([e]),S(")"),t.parens=!0,t},multiplication:function(){var e,t,n,r,u,a=[];if(e=w(this.operand)){u=b(s.charAt(o-1));while(!T(/^\/[*\/]/)&&(n=w("/")||w("*"))){if(!(t=w(this.operand)))break;e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1))}return r||e}},addition:function(){var e,t,n,r,u;if(e=w(this.multiplication)){u=b(s.charAt(o-1));while((n=w(/^[-+]\s+/)||!u&&(w("+")||w("-")))&&(t=w(this.multiplication)))e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1));return r||e}},conditions:function(){var e,t,n=o,r;if(e=w(this.condition)){while(w(",")&&(t=w(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;w(/^not/)&&(u=!0),S("(");if(e=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(r=w(/^(?:>=|=<|[<=>])/))?(t=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):x("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),S(")"),w(/^and/)?new i.Condition("and",n,w(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=w("-"));var n=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return e&&(n.parensInOp=!0,n=new i.Negative(n)),n},expression:function(){var e,t,n=[],r;while(e=w(this.addition)||w(this.entity))n.push(e),!T(/^\/[\/*]/)&&(t=w("/"))&&n.push(new i.Anonymous(t));if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=w(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.currentDirectory&&(e=t.currentDirectory+e);var i=r.toSheet(e);i.processImports=!1,i.currentFileInfo=t,w(i,function(e,t,r,i,s,o){n.call(null,e,t,o)},!0)};(function(r){function u(e){return r.functions.hsla(e.h,e.s,e.l,e.a)}function a(e,t){return e instanceof r.Dimension&&e.unit.is("%")?parseFloat(e.value*t/100):f(e)}function f(e){if(e instanceof r.Dimension)return parseFloat(e.unit.is("%")?e.value/100:e.value);if(typeof e=="number")return e;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function l(e){return Math.min(1,Math.max(0,e))}r.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(e,t,n,i){var s=[e,t,n].map(function(e){return a(e,256)});return i=f(i),new r.Color(s,i)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function o(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?s+(i-s)*e*6:e*2<1?i:e*3<2?s+(i-s)*(2/3-e)*6:s}e=f(e)%360/360,t=l(f(t)),n=l(f(n)),r=l(f(r));var i=n<=.5?n*(t+1):n+t-n*t,s=n*2-i;return this.rgba(o(e+1/3)*255,o(e)*255,o(e-1/3)*255,r)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,r){e=f(e)%360/360*360,t=f(t),n=f(n),r=f(r);var i,s;i=Math.floor(e/60%6),s=e/60-i;var o=[n,n*(1-t),n*(1-s*t),n*(1-(1-s)*t)],u=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(o[u[i][0]]*255,o[u[i][1]]*255,o[u[i][2]]*255,r)},hue:function(e){return new r.Dimension(Math.round(e.toHSL().h))},saturation:function(e){return new r.Dimension(Math.round(e.toHSL().s*100),"%")},lightness:function(e){return new r.Dimension(Math.round(e.toHSL().l*100),"%")},hsvhue:function(e){return new r.Dimension(Math.round(e.toHSV().h))},hsvsaturation:function(e){return new r.Dimension(Math.round(e.toHSV().s*100),"%")},hsvvalue:function(e){return new r.Dimension(Math.round(e.toHSV().v*100),"%")},red:function(e){return new r.Dimension(e.rgb[0])},green:function(e){return new r.Dimension(e.rgb[1])},blue:function(e){return new r.Dimension(e.rgb[2])},alpha:function(e){return new r.Dimension(e.toHSL().a)},luma:function(e){return new r.Dimension(Math.round(e.luma()*e.alpha*100),"%")},saturate:function(e,t){var n=e.toHSL();return n.s+=t.value/100,n.s=l(n.s),u(n)},desaturate:function(e,t){var n=e.toHSL();return n.s-=t.value/100,n.s=l(n.s),u(n)},lighten:function(e,t){var n=e.toHSL();return n.l+=t.value/100,n.l=l(n.l),u(n)},darken:function(e,t){var n=e.toHSL();return n.l-=t.value/100,n.l=l(n.l),u(n)},fadein:function(e,t){var n=e.toHSL();return n.a+=t.value/100,n.a=l(n.a),u(n)},fadeout:function(e,t){var n=e.toHSL();return n.a-=t.value/100,n.a=l(n.a),u(n)},fade:function(e,t){var n=e.toHSL();return n.a=t.value/100,n.a=l(n.a),u(n)},spin:function(e,t){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,u(n)},mix:function(e,t,n){n||(n=new r.Dimension(50));var i=n.value/100,s=i*2-1,o=e.toHSL().a-t.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[e.rgb[0]*u+t.rgb[0]*a,e.rgb[1]*u+t.rgb[1]*a,e.rgb[2]*u+t.rgb[2]*a],l=e.alpha*i+t.alpha*(1-i);return new r.Color(f,l)},greyscale:function(e){return this.desaturate(e,new r.Dimension(100))},contrast:function(e,t,n,r){if(!e.rgb)return null;typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1));if(t.luma()>n.luma()){var i=n;n=t,t=i}return typeof r=="undefined"?r=.43:r=f(r),e.luma()*e.alpha=d){if(this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",o,v,d),(new r.URL(i||t,this.currentFileInfo)).eval(this.env);this.env.silent||console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!",o,v,d)}p=f?p.toString("base64"):encodeURIComponent(p);var m="'data:"+s+","+p+"'";return new r.URL(new r.Anonymous(m))}},r._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(e){var i=n("path").extname(e),s=r._mime._types[i];if(s===t)throw new Error('Optional dependency "mime" is required for '+i);return s},charsets:{lookup:function(e){return e&&/^text\//.test(e)?"UTF-8":""}}};var i=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],s=function(e,t){return function(n){return t!=null&&(n=n.unify()),this._math(Math[e],t,n)}};for(var o=0;o255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("");return n&&(r=r.split(""),r[0]==r[1]&&r[2]==r[3]&&r[4]==r[5]?r=r[0]+r[2]+r[4]:r=r.join("")),"#"+r},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(t,n,this.rgb[s],r.rgb[s]);return new e.Color(i,this.alpha+r.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={type:"Comment",toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype={type:"Condition",accept:function(e){this.lvalue=e.visit(this.lvalue),this.rvalue=e.visit(this.rvalue)},eval:function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}}(n("../tree")),function(e){e.Dimension=function(n,r){this.value=parseFloat(n),this.unit=r&&r instanceof e.Unit?r:new e.Unit(r?[r]:t)},e.Dimension.prototype={type:"Dimension",accept:function(e){this.unit=e.visit(this.unit)},eval:function(e){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(e){if(e&&e.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var t=this.value,n=String(t);t!==0&&t<1e-6&&t>-0.000001&&(n=t.toFixed(20).replace(/0+$/,""));if(e&&e.compress){if(t===0&&!this.unit.isAngle())return n;t>0&&t<1&&(n=n.substr(1))}return n+this.unit.toCSS(e)},operate:function(t,n,r){var i=e.operate(t,n,this.value,r.value),s=this.unit.clone();if(n==="+"||n==="-"){if(s.numerator.length===0&&s.denominator.length===0)s.numerator=r.unit.numerator.slice(0),s.denominator=r.unit.denominator.slice(0);else if(r.unit.numerator.length!=0||s.denominator.length!=0){r=r.convertTo(this.unit.usedUnits());if(t.strictUnits&&r.unit.toString()!==s.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+s.toString()+"' and '"+r.unit.toString()+"'.");i=e.operate(t,n,this.value,r.value)}}else n==="*"?(s.numerator=s.numerator.concat(r.unit.numerator).sort(),s.denominator=s.denominator.concat(r.unit.denominator).sort(),s.cancel()):n==="/"&&(s.numerator=s.numerator.concat(r.unit.denominator).sort(),s.denominator=s.denominator.concat(r.unit.numerator).sort(),s.cancel());return new e.Dimension(i,s)},compare:function(t){if(t instanceof e.Dimension){var n=this.unify(),r=t.unify(),i=n.value,s=r.value;return s>i?-1:s=1?this.numerator[0]:this.denominator.length>=1?this.denominator[0]:(!e||!e.strictUnits)&&this.backupUnit?this.backupUnit:""},toString:function(){var e,t=this.numerator.join("*");for(e=0;e0)for(n=0;n":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={type:"Expression",accept:function(e){this.value=e.visit(this.value)},eval:function(t){var n,r=this.parens&&!this.parensInOp,i=!1;return r&&t.inParenthesis(),this.value.length>1?n=new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?(this.value[0].parens&&!this.value[0].parensInOp&&(i=!0),n=this.value[0].eval(t)):n=this,r&&t.outOfParenthesis(),this.parens&&this.parensInOp&&!t.isMathOn()&&!i&&(n=new e.Paren(n)),n},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")},throwAwayComments:function(){this.value=this.value.filter(function(t){return!(t instanceof e.Comment)})}}}(n("../tree")),function(e){e.Extend=function(t,n,r){this.selector=t,this.option=n,this.index=r;switch(n){case"all":this.allowBefore=!0,this.allowAfter=!0;break;default:this.allowBefore=!1,this.allowAfter=!1}},e.Extend.prototype={type:"Extend",accept:function(e){this.selector=e.visit(this.selector)},eval:function(t){return new e.Extend(this.selector.eval(t),this.option,this.index)},clone:function(t){return new e.Extend(this.selector,this.option,this.index)},findSelfSelectors:function(e){var t=[],n;for(n=0;n1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t){var n=[],r=[],i=[],s=[],o,u,a;for(var f=0;f0){u=e.debugInfo(t,this),o=this.paths.map(function(e){return e.map(function(e){return e.toCSS(t)}).join("").trim()}).join(t.compress?",":",\n");for(var f=r.length-1;f>=0;f--)(r[f].slice(0,2)==="/*"||i.indexOf(r[f])===-1)&&i.unshift(r[f]);r=i,n.push(u+o+(t.compress?"{":" {\n ")+r.join(t.compress?"":"\n ")+(t.compress?"}":"\n}\n"))}return n.push(s),n.join("")+(t.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0),r.extendList),v=!1):d=new e.Selector([],r.extendList),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0&&t.push(a[i])},mergeElementsOnToSelectors:function(t,n){var r,i,s;if(n.length==0){n.push([new e.Selector(t)]);return}for(r=0;r0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t),i[i.length-1].extendList):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e,t){this.elements=e,this.extendList=t||[]},e.Selector.prototype={type:"Selector",accept:function(e){this.elements=e.visit(this.elements),this.extendList=e.visit(this.extendList)},match:function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree")),function(e){var t=["paths","optimization","files","contents","relativeUrls","strictImports","dumpLineNumbers","compress","processImports","syncImport","mime","currentFileInfo"];e.parseEnv=function(e){r(e,this,t),this.contents||(this.contents={}),this.files||(this.files={});if(!this.currentFileInfo){var n=e&&e.filename||"input",i=n.replace(/[^\/\\]*$/,"");e&&(e.filename=null),this.currentFileInfo={filename:n,relativeUrls:this.relativeUrls,rootpath:e&&e.rootpath||"",currentDirectory:i,entryPath:i,rootFilename:n}}},e.parseEnv.prototype.toSheet=function(t){var n=new e.parseEnv(this);return n.href=t,n.type=this.mime,n};var n=["silent","verbose","compress","yuicompress","ieCompat","strictMath","strictUnits"];e.evalEnv=function(e,t){r(e,this,n),this.frames=t||[]},e.evalEnv.prototype.inParenthesis=function(){this.parensStack||(this.parensStack=[]),this.parensStack.push(!0)},e.evalEnv.prototype.outOfParenthesis=function(){this.parensStack.pop()},e.evalEnv.prototype.isMathOn=function(){return this.strictMath?this.parensStack&&this.parensStack.length:!0},e.evalEnv.prototype.isPathRelative=function(e){return!/^(?:[a-z-]+:|\/)/.test(e)};var r=function(e,t,n){if(!e)return;for(var r=0;r100){var d="{unable to calculate}",v="{unable to calculate}";try{d=u[0].selfSelectors[0].toCSS(),v=u[0].selector.toCSS()}catch(m){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+d+":extend("+v+")"}}return u.concat(f.doExtendChaining(u,n,r+1))}return u},inInheritanceChain:function(e,t){if(e===t)return!0;if(t.parents){if(this.inInheritanceChain(e,t.parents[0]))return!0;if(this.inInheritanceChain(e,t.parents[1]))return!0}return!1},visitRule:function(e,t){t.visitDeeper=!1},visitMixinDefinition:function(e,t){t.visitDeeper=!1},visitSelector:function(e,t){t.visitDeeper=!1},visitRuleset:function(e,t){if(e.root)return;var n,r,i,s=this.allExtendsStack[this.allExtendsStack.length-1],o=[],u=this,a;for(i=0;i0&&f[c.matched].combinator.value!==o?c=null:c.matched++,c&&(c.finished=c.matched===f.length,c.finished&&!e.allowAfter&&(i+1i&&s>0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,l.pathIndex)),o.push(new e.Selector(a.elements.slice(s,l.index).concat([f]).concat(r.elements.slice(1)))),i=l.endPathIndex,s=l.endPathElementIndex,s>=a.elements.length&&(s=0,i++);return i0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,n.length)),o},visitRulesetOut:function(e){},visitMedia:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitMediaOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitDirectiveOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d ul > li:first-child { + display: inline; +} +.head .nav input[name=q] { + width: 12em; + border-radius: 2px; + padding: 2px; + background-color: #000000; + color: #ffffff; + border: 1px solid #397ab6; + margin-right: 0.6em; +} +.head .nav input[name=q]:focus { + outline: 2px solid #397ab6; +} +/* + * title + */ +.slot_title { + padding-left: 12pt; + padding-right: 12pt; + font: bold 12pt / 125% sans-serif; + color: #ffffff; + padding-top: 12pt; +} +.slot_title a { + color: #ffffff; + display: inline-block; +} +.slot_title a.home { + margin-right: 4px; +} +.slot_title a.delegation_info { + margin-right: 0; +} +.slot_title .initiative, +.slot_title a .label { + display: none; +} +.slot_title .delegation_info { + background-color: #ffffff; + color: #000000; + border-radius: 2px; + padding-right: 3px; + margin-bottom: 12pt; +} +.slot_title .delegation_info a { + color: #000000; +} +.content { + clear: both; + margin: 0 12pt; + margin-top: 12pt; +} +/* + * the sidebar + */ +.sidebar { + float: right; + width: 30%; +} +.sidebarSection { + background-color: #ffffff; + border-radius: 2px; + color: #000000; + margin-bottom: 12pt; + padding: 0; +} +.sidebarSection .sidebarHead { + padding: 9px 9px 4.5px 9px; + background: #ffffff; + color: #000000; + min-height: 20px; +} +.sidebarSection .sidebarHead a { + color: #000000; +} +.sidebarSection .sidebarHead .icon24 { + margin-top: -3.6px; +} +.sidebarSection .sidebarRow { + clear: right; + display: block; + border-top: 1px solid #aaaaaa; + padding: 4.5px 9px; + min-height: 20px; +} +.sidebarSection .sidebarRow.highlighted { + background-color: #e7f0ff; +} +.sidebarSection .sidebarRow.sidebarRowNarrow { + padding: 2.25px 9px; +} +.sidebarSection .sidebarRow.moreLink { + min-height: 0; +} +.sidebarSection h1, +.sidebarSection h1 a, +.sidebarSection h2, +.sidebarSection h2 a, +.sidebarSection h3, +.sidebarSection h3 a { + color: #000000; +} +.sidebarSection a { + color: #222277; +} +.sidebarSection .areas .whenfolded { + display: none; +} +.sidebarSection .areas.folded .whenunfolded { + display: none; +} +.sidebarSection .areas.folded .whenfolded { + display: block; +} +.sidebarSection .areas.folded .disabled { + display: none; +} +.sidebarSection a.issue { + font: bold 12pt / 125% sans-serif; + color: #000000; +} +.sidebarSection ul.initiatives li { + padding: 4.5px 9px; + border-top: 1px solid #aaaaaa; +} +.sidebarSection ul.initiatives li .bargraph { + display: block; +} +.sidebarSection ul.initiatives li .supporterCount { + white-space: nowrap; +} +.sidebarSection ul.initiatives .revoked .initiative_name { + text-decoration: line-through; +} +.sidebarSection ul.initiatives li.highlighted { + background-color: #e7f0ff; +} +.sidebarSection ul.initiatives li.highlighted:last-child { + border-radius: 0 0 2px 2px; +} +.sidebarSection .supporters { + line-height: 28.799999999999997px; +} +.sidebarSection .supportCount { + color: #00c000; + font: bold 12pt / 125% sans-serif; + float: right; +} +.sidebarSection .member_list .member_thumb { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.sidebarSection .member_list .member_thumb img.member_image { + width: 24px; + height: 24px; + vertical-align: middle; + margin-right: 0.2em; +} +.sidebarSection .member_list .member_thumb.in_delegation_chain { + font-weight: bold; +} +.sidebarSection > div { + position: relative; +} +.sidebarSection > div:first-child { + margin-top: 0; + border-radius: 2px 2px 0 0; +} +.sidebarSection > div:last-child { + border-radius: 0 0 2px 2px; +} +.sidebarSection > div:last-child:first-child { + border-radius: 2px; +} +.sidebarSection a.unit { + font: normal 12pt / 125% sans-serif; +} +.sidebarSection a.area { + margin-left: 25px; + display: block; +} +.sidebarSection .star { + float: left; +} +.sidebarSection .delegation_info { + margin-top: -3.6px; + margin-bottom: 1px; +} +.admitted_info h1 { + color: #00aa00; +} +.not_admitted_info h1, +.revoked_info h1 { + color: #aa0000; +} +.admitted_info .initiative_pie, +.not_admitted_info .initiative_pie { + float: right; +} +.admitted_info table tr th, +.not_admitted_info table tr th { + text-align: left; +} +.admitted_info table tr td, +.not_admitted_info table tr td { + text-align: right; + padding: 0.3ex 0.4em; +} +/* + * main area + */ +.main_outer { + width: 70%; +} +.main { + clear: left; + margin-right: 12pt; + border-radius: 2px; + /* + * tabs und filter + */ + /* + * initiative + */ + /* the draft */ +} +.main .section .sectionHead, +.main .section .sectionRow { + background-color: #ffffff; + overflow: auto; + padding: 9px; +} +.main .section .sectionHead { + background-color: #ffffff; + color: #000000; + margin-top: 12pt; + border-radius: 2px 2px 0 0; +} +.main .section .sectionHead:first-child { + margin-top: 0; +} +.main .section .sectionHead:last-child { + border-radius: 2px; +} +.main .section .sectionRow { + margin-top: 4px; +} +.main .section .sectionRow:last-child { + border-radius: 0 0 2px 2px; + margin-bottom: 12pt; +} +.main > h1 { + border-bottom: 1px solid #aaaaaa; + padding: 9px; +} +.main .ui_filter .ui_filter_head { + background: #ffffff; + color: #000000; + padding: 0 9px 9px 9px; + vertical-align: middle; +} +.main .ui_filter .ui_filter_head a { + white-space: nowrap; + font: normal 10pt / 150% sans-serif; + margin-right: 0.5em; +} +.main .ui_filter .ui_filter_head a.active { + font: bold 10pt / 150% sans-serif; + text-decoration: none; + color: #000000; +} +.main .ui_filter .ui_filter_head select { + background: #ffffff; + color: #444444; + font: normal 10pt / 150% sans-serif; + border: none; + padding: 0; + margin: 0; +} +.main .ui_filter .ui_filter_head select option { + color: #000000; +} +.main .ui_filter .ui_filter_head select option:first-child, +.main .ui_filter .ui_filter_head select option[value="interest_direct"], +.main .ui_filter .ui_filter_head select option[value="interest_delegated"], +.main .ui_filter .ui_filter_head select option[value="support_direct"], +.main .ui_filter .ui_filter_head select option[value="support_delegated"], +.main .ui_filter .ui_filter_head select option[value="potential_support_direct"], +.main .ui_filter .ui_filter_head select option[value="potential_support_delegated"] { + color: #444444; +} +.main .ui_filter .ui_filter_head select.active { + color: #000000; +} +.main .ui_filter .ui_filter_head:first-child { + border-radius: 2px 2px 0 0; + padding-top: 9px; +} +.main .ui_filter .ui_filter_head.filter_filter { + padding-top: 9px; +} +.main .ui_filter .ui_filter_head.filter_mode { + padding-top: 9px; + margin-bottom: 0; + padding-bottom: 0; +} +.main .ui_filter .ui_filter_head.subfilter a { + font: normal 10pt / 150% sans-serif; +} +.main .ui_filter .ui_filter_head.subfilter a.active { + font: bold 10pt / 150% sans-serif; +} +.main .filter { + float: right; +} +.main .delegation_info.suspended { + margin: 1ex -2px -2px -2px; +} +.main .issues .state_info { + font: bold 10pt / 125% sans-serif; + color: #007700; +} +.main .issues .state_info.negative { + color: #aa0000; +} +.main ul.initiatives li { + margin-top: 1ex; +} +.main ul.initiatives li .bargraph { + float: left; + margin-top: 5px; + margin-right: 0.5em; +} +.main ul.initiatives li .initiative_name { + display: block; + margin-left: 110px; +} +.main ul.initiatives li .rank1 .initiative_name { + margin-left: 0; +} +.main ul.initiatives li .revoked .initiative_name { + text-decoration: line-through; +} +.main ul.initiatives li:first-child { + margin-top: 0; + clear: none; +} +.main .events .event ul.initiatives li .initiative_name { + margin-left: 0; +} +.main .member_photo { + float: right; +} +.main .member_thumb.in_delegation_chain { + font-weight: bold; +} +.main .support { + color: #aaa; + line-height: 80%; + float: right; + width: 102px; +} +.main .initiativeInfo { + font-family: normal 10pt / 125% sans-serif; + line-height: 24px; + overflow: auto; +} +.main .initiativeInfo .support { + margin-top: 1ex; + float: left; + width: auto; +} +.main .initiativeInfo .mySupport { + line-height: 125%; + min-width: 12em; + text-align: right; +} +.main .initiativeInfo .initiators { + margin-top: 1.5ex; + margin-bottom: -1ex; + float: left; +} +.main .initiativeInfo .links { + margin-top: 1.5ex; + margin-bottom: -1ex; + float: right; + clear: right; +} +.main .initiativeInfo .initiator_links { + clear: right; +} +.main .issueInfo .links { + margin-top: 1.5ex; + margin-bottom: -1ex; + float: right; + clear: both; +} +.main .draft_updated_info { + color: #007700; +} +.main .draft_updated_info .info { + font: bold 10pt / 125% sans-serif; +} +.main .draft { + font: normal 10pt / 125% sans-serif; +} +.main .draft ul { + margin-left: 1em; + margin-bottom: 1.5ex; + list-style: square; + padding-left: 1em; +} +.main .draft h1 { + font: italic 10pt / 125% sans-serif; + font-size: 125%; + border-bottom: 1px solid #444444; + margin-bottom: 1ex; +} +.main .draft h2 { + font: normal 10pt / 125% sans-serif; + font-size: 125%; +} +.main .draft h3 { + font: normal 10pt / 125% sans-serif; + font-size: 125%; +} +.main .draft h4 { + font: normal 10pt / 125% sans-serif; +} +.main .draft hr { + border: none; + border-top: 1px solid #000000; +} +.main .draft b, +.main .draft strong { + font: italic 10pt / 125% sans-serif; +} +.main .draft i, +.main .draft em { + font: normal 10pt / 125% sans-serif; +} +.main form, +.main .form { + margin: 0; + padding: 0; +} +.main form .ui_field_label, +.main .form .ui_field_label { + display: inline-block; + width: 25%; + margin: 0; + padding: 0; + text-align: right; + margin-bottom: 9px; + padding-right: 0.5%; + vertical-align: top; + color: #444444; +} +.main form input[type=text], +.main .form input[type=text], +.main form input[type=password], +.main .form input[type=password], +.main form select, +.main .form select, +.main form textarea, +.main .form textarea { + vertical-align: top; + width: 73%; + margin: 0; + padding: 3px; + border: 1px solid #444444; + font: bold 10pt / 125% sans-serif; + margin-bottom: 9px; +} +.main form input:focus, +.main .form input:focus { + outline: 2px solid #397ab6; +} +.main form .actions, +.main .form .actions { + margin-left: 26%; +} +.main form.wide input[type=text], +.main form.wide input[type=password], +.main form.wide select, +.main form.wide textarea { + width: 100%; +} +.issues .event .initiative_pie, +.events .event .initiative_pie { + clear: right; + float: right; +} +.issues .event ul.initiatives .initiative_info_left, +.events .event ul.initiatives .initiative_info_left { + display: inline; + margin-right: 0.5em; +} +.issues .event ul.initiatives .initiative_info_right, +.events .event ul.initiatives .initiative_info_right { + float: right; +} +.issues .event ul.initiatives .initiative_info_right .bargraph, +.events .event ul.initiatives .initiative_info_right .bargraph { + float: right; + margin-left: 0.5em; +} +.issues .event ul.initiatives .result, +.events .event ul.initiatives .result { + color: #444444; + margin-top: 0.5ex; +} +.issues .event ul.initiatives h3, +.events .event ul.initiatives h3 { + margin-top: 1ex; + margin-bottom: 0; +} +.issues .event ul.initiatives a.initiative, +.events .event ul.initiatives a.initiative { + font: bold 10pt / 125% sans-serif; +} +.issues .event .event_info, +.events .event .event_info { + font: bold 10pt / 125% sans-serif; + color: #007700; + margin-top: 0.66ex; + margin-bottom: 1ex; +} +.issues .event .event_info:last-child, +.events .event .event_info:last-child { + margin-bottom: 0; +} +.issues .event .event_info.negative, +.events .event .event_info.negative { + color: #aa0000; +} +.issues .event .event_time, +.events .event .event_time { + font: normal 10pt / 125% sans-serif; + color: #444444; +} +.issues .event:hover .event_time, +.events .event:hover .event_time { + visibility: visible; +} +.issues .event:hover ul.initiatives div, +.events .event:hover ul.initiatives div { + visibility: visible; +} +.issues .issue_context, +.events .issue_context { + line-height: 24px; + margin-bottom: 0.66ex; +} +.issues .issue_context .unit, +.events .issue_context .unit { + background-color: #777; + color: #fff; + padding: 1px 3px; + border-radius: 2px; + text-decoration: none; +} +.issues .issue_context .area, +.events .issue_context .area { + background-color: #ddd; + color: #000; + padding: 1px 3px; + border-radius: 2px; + text-decoration: none; +} +.issues .issue_info .issue, +.events .issue_info .issue { + font: bold 10pt / 125% sans-serif; + color: #000000; +} +.issues img.star, +.events img.star { + vertical-align: middle; + float: right; + margin-left: 0.5em; +} +.issues .event.suggestion ul.initiatives li, +.events .event.suggestion ul.initiatives li { + margin-top: 0; + margin-bottom: 1ex; +} +.issues .event.suggestion ul.initiatives li a, +.events .event.suggestion ul.initiatives li a { + font: normal 10pt / 125% sans-serif; +} +.issues .event.suggestion .suggestion, +.events .event.suggestion .suggestion { + font: bold 10pt / 125% sans-serif; + overflow: hidden; + text-overflow: ellipsis; +} +.suggestions .suggestion .opinion { + float: right; +} +.suggestions .suggestion .opinion .must { + background-color: #00cc00; + color: #ffffff; +} +.suggestions .suggestion .opinion .should { + background-color: #44aa44; + color: #ffffff; +} +.suggestions .suggestion .opinion .shouldnot { + background-color: #aa4444; + color: #ffffff; +} +.suggestions .suggestion .opinion .mustnot { + background-color: #cc0000; + color: #ffffff; +} +.suggestions .suggestion .opinion .implemented { + background-color: #00cc00; + color: #ffffff; +} +.suggestions .suggestion .opinion .notimplemented { + background-color: #cc0000; + color: #ffffff; +} +.suggestions .suggestion .suggestion-rating { + float: right; +} +.suggestions .suggestion .suggestion-text { + margin-top: 9px; + font: normal 10pt / 125% sans-serif; + overflow: hidden; + text-overflow: ellipsis; + position: relative; + z-index: 10; +} +.suggestions .suggestion .suggestion-more { + display: none; +} +.suggestions .suggestion .suggestion-less { + display: none; +} +.suggestions .suggestion .suggestionHead { + overflow: hidden; + text-overflow: ellipsis; +} +.suggestions .suggestion .rating { + display: none; + padding: 4.5px 0; +} +.suggestions .suggestion .rating .active-plus2 { + background-color: #00cc00; + color: #ffffff; +} +.suggestions .suggestion .rating .active-plus1 { + background-color: #44aa44; + color: #ffffff; +} +.suggestions .suggestion .rating .active-minus1 { + background-color: #aa4444; + color: #ffffff; +} +.suggestions .suggestion .rating .active-minus2 { + background-color: #cc0000; + color: #ffffff; +} +.suggestions .suggestion .rating .active-notfulfilled { + background-color: #faa; +} +.suggestions .suggestion .rating .active-fulfilled { + background-color: #afa; +} +.suggestions .suggestion.rateable .suggestion-more { + display: block; +} +.suggestions .suggestion.rateable.unfolded .rating { + border-top: 3px solid #397ab6; +} +.suggestions .suggestion.folded .suggestion-more { + display: block; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + box-shadow: inset 0 -12ex 10ex -5ex #ffffff; + padding-top: 5ex; +} +.suggestions .suggestion.unfolded .suggestion-more { + display: none; +} +.suggestions .suggestion.unfolded .rating { + display: block; +} +.suggestions .suggestion.unfolded .suggestion-less { + margin-top: 1ex; + display: block; +} +.suggestions .suggestion.highlighted { + background-color: #e7f0ff; +} +.suggestions .suggestion.highlighted .suggestion-more { + box-shadow: inset 0 -12ex 10ex -5ex #e7f0ff; +} +li.raw { + list-style: none; + padding: 0; + margin: 0 !important; +} +.satisfiedSupporterCount { + color: #070; +} +.potentialSupporterCount { + color: #960; +} +.bargraph { + display: inline-block; + vertical-align: top; + height: 9px; +} +.bargraph div { + margin: 0; + padding: 0; + display: inline-block; + height: 9px; +} +.diff .diff_added { + background-color: #cfc; +} +.diff .diff_removed { + text-decoration: line-through; + background-color: #fcc; +} +.btn, +.ui_paginate_foot a { + text-decoration: none; + min-width: 2em; + text-align: center; + display: inline-block; + border-radius: 5px; + border: none; + font: bold 10pt / 125% sans-serif; + background-color: #999; + color: #fff !important; + margin-bottom: 5px; +} +.btn { + padding: 1ex 1em; +} +.ui_paginate_foot a { + padding: 0.5ex 0.5em; + background-color: #eee; + color: 000 !important; +} +.ui_paginate_foot a.active { + background-color: #666; + color: #fff !important; +} +.btn-default { + background-color: #47a; + color: #fff !important; +} +.btn:hover, +.btn:focus, +.ui_paginate_foot a:hover, +.ui_paginate_foot a:focus { + background-color: #0a0; + color: #fff !important; + cursor: pointer; +} +.btn-dangerous:hover { + background-color: #c00; + color: #fff !important; +} +.btn-link { + font: normal 10pt / 125% sans-serif; + background-color: #ffffff; + color: #222277; + border: none; + padding: 0; + margin: 0; + text-decoration: underline; + cursor: pointer; +} +/************************************************************************* + * Voting + */ +.main .section #voting_form .sectionRow:last-child { + border-radius: 0; + margin-bottom: 0; +} +#voting { + background: #ddd; + padding: 9px; + margin-top: 4px; + position: relative; + margin-bottom: 2ex; +} +#voting .approval, +#voting .abstention, +#voting .disapproval { + border: 2px black solid; + margin-bottom: 2ex; + padding: 1ex; + padding-bottom: 2ex; + border-radius: 2px; +} +#voting .disapproval { + margin-bottom: 2ex; +} +#voting .approval { + background-color: #9f9; +} +#voting .approval .movable { + background-color: #dfd; +} +#voting .abstention { + background-color: #ccc; +} +#voting .abstention .movable { + background-color: #f2f2f2; +} +#voting .disapproval { + background-color: #f88; +} +#voting .disapproval .movable { + background-color: #fbb; +} +#voting .movable { + position: relative; + border: 1px black solid; + margin-top: 1ex; + padding: 0.5ex; + border-radius: 2px; +} +#voting .voting_form_active .movable { + cursor: pointer; + vertical-align: middle; + cursor: move; +} +#voting .voting_form_active .clickable { + cursor: auto; +} +#voting .voting_form_active a.clickable { + cursor: pointer; +} +/* + * footer + */ +.footer { + text-align: center; + color: #ffffff; + background-color: #000000; + padding: 9px 0; + border: 1px solid #000; + border-top: none; +} +.footer a { + color: #ffffff; +} +.ui_paginate_head { + display: none; +} +.ui_paginate_foot { + line-height: 180%; +} +.swiper_tabs { + display: none; +} +#swiper_info { + display: none; +} +.nav .searchLink { + display: none; +} +@media (max-width: 767px) { + html body { + margin: 0; + background: #255078; + } + html body .head { + margin: 6pt; + padding: 0; + } + html body .head .logo { + display: block; + padding: 0; + } + html body .head .logo .liquid, + html body .head .logo .feedback { + font: bold 12pt / 125% sans-serif; + } + html body .head .logo .instanceName { + font: normal 10pt / 100% sans-serif; + display: block; + margin-left: 0; + } + html body .head .nav { + padding: 0; + } + html body .initiativeInfo h1 { + display: none; + } + html body .slot_title { + font: normal 12pt / 125% sans-serif; + padding: 0; + margin: 0 6pt; + } + html body .slot_title .spacer { + display: none; + } + html body .slot_title .unit, + html body .slot_title .area, + html body .slot_title .issue, + html body .slot_title .initiative, + html body .slot_title .member { + display: block; + margin-right: 0; + padding: 4px 0; + border-radius: 2px; + overflow: auto; + } + html body .slot_title .unit:before, + html body .slot_title .area:before, + html body .slot_title .issue:before, + html body .slot_title .initiative:before, + html body .slot_title .member:before { + content: "↳"; + position: relative; + top: -2px; + } + html body .slot_title .area { + margin-left: 10px; + } + html body .slot_title .issue { + margin-left: 20px; + } + html body .slot_title .initiative { + margin-left: 30px; + } + html body .slot_title a:last-child, + html body .slot_title .issue:last-child, + html body .slot_title .area:last-child, + html body .slot_title .unit:last-child, + html body .slot_title .initiative:last-child { + margin-bottom: 6pt; + } + html body .slot_title .unit a, + html body .slot_title .initiative a, + html body .slot_title .issue a, + html body .slot_title .area a { + margin-bottom: 0; + display: inline; + } + html body .slot_title a.home { + display: none; + } + html body .slot_title .weight { + float: right; + margin: 0; + } + html body .slot_title .delegation_info { + float: right; + display: block; + margin-top: -10px; + } + html body .slot_title a .label { + display: inline; + } + html body .slot_title .star { + float: right; + margin-left: 0.5em; + margin-top: -4.5px; + margin-bottom: -4.5px; + } + html body .slot_title > span > *:last-child { + font: bold 12pt / 125% sans-serif; + } + html body .page { + background: none; + margin: 0; + box-shadow: none; + } + html body .nav #member_menu .text { + display: none; + } + html body .nav form.search { + display: none; + } + html body .nav .notifications, + html body .nav .searchLink, + html body .nav #member_menu a { + vertical-align: middle; + display: inline-block; + height: 48px; + min-width: 35px; + text-align: center; + background-color: #000; + border: 1px solid #777; + border-radius: 2px; + margin: 0; + } + html body .nav .notifications img, + html body .nav .searchLink img, + html body .nav #member_menu a img { + margin: 0; + width: 48px; + height: 48px; + } + html body .nav .notifications { + padding: 12px 2px; + height: 24px; + } + html body .nav #member_menu a :last-child { + display: none; + } + html body .notifications span { + margin-left: -5px; + } + html body .swiper_tabs { + clear: both; + display: block; + overflow: auto; + margin: 6pt; + } + html body .swiper_tabs div { + display: block; + float: left; + width: 33.333%; + } + html body .swiper_tabs div a { + padding: 8px 0; + display: block; + text-align: center; + background-color: #eee; + } + html body .swiper_tabs div a.active { + background-color: #abe; + } + html body .swiper_tabs div:first-child a { + border-radius: 2px 0 0 2px; + } + html body .swiper_tabs div:last-child a { + border-radius: 0 2px 2px 0; + } + html body #swiper_info.active { + display: block; + font: bold 10pt / 125% sans-serif; + z-index: 1; + text-align: center; + width: 100%; + background-color: #255078; + color: #ffffff; + } + html body .sidebarSection { + margin: 0 6pt 6pt 6pt; + } + html body .main, + html body .extra > .section { + clear: none; + float: none; + width: auto; + margin: 0 6pt 6pt 6pt; + } + html body .main .section .sectionRow:last-child, + html body .extra > .section .section .sectionRow:last-child { + margin-bottom: 6pt; + } + html body .ui_filter_head.filter_mode { + float: none !important; + background: #ffffff !important; + text-align: left !important; + border-radius: 2px; + margin-bottom: 6pt !important; + } + html body .member_photo { + text-align: center; + margin-bottom: 2ex; + } + html body .member_photo .member_image_photo { + max-width: 600px; + } + html body #trace_content { + margin: 6pt 0; + border-radius: 0; + } + html body #trace_content ul li .trace_head { + padding: 6px 5px; + } + html body #trace_content ul ul { + padding: 5px 2px; + } +} +.textCenter { + text-align: center; +} +a.initiative { + text-decoration: none; + border-bottom: 1px solid #66c; +} +a.initiative:hover { + border-bottom: 1px solid #007; +} +#trace_content { + margin: 12pt; + padding: 9px; + border-radius: 2px; + background-color: #ffffff; +} +#trace_content #system_error { + font-family: monospace; +} +#trace_content ul li { + margin-top: 10px; +} +#trace_content ul li .trace_head { + padding: 3px 5px; + border-radius: 2px 2px 0 0; +} +#trace_content ul li .trace_head:last-child { + border-radius: 2px; +} +#trace_content ul li ul { + border-radius: 0 0 2px 2px; +} +#trace_content ul li:first-child { + margin-top: 0; +} +#trace_content ul ul { + padding: 10px; +} +#trace_content .trace_config > ul { + background-color: #eee; + border: 1px solid #ccc; +} +#trace_content .trace_config > .trace_head { + background-color: #ccc; + color: #000; +} +#trace_content .trace_request > ul { + background-color: #afa; +} +#trace_content .trace_request > .trace_head { + background-color: #0c0; +} +#trace_content .trace_filter > ul { + background-color: #ccf; + border: 1px solid #00c; + border-top: none; +} +#trace_content .trace_filter > .trace_head { + background-color: #00c; + color: #fff; +} +#trace_content .trace_view > ul { + background-color: #cfc; + border: 1px solid #0c0; + border-top: none; +} +#trace_content .trace_view > .trace_head { + background-color: #0c0; + color: #000; +} +#trace_content .trace_action_neutral > ul { + background-color: #ffa; + border: 1px solid #fe0; +} +#trace_content .trace_action_neutral > .trace_head { + background-color: #fe0; + color: #000; +} +#trace_content .trace_sql { + background-color: #fff; + padding: 2px 4px; + margin-top: 8px; +} +#trace_content .trace_error { + background-color: #faa; + color: #000; + font-weight: bold; + border: 1px solid #c00; +} +#trace_content .trace_exectime { + background-color: #ccc; + font-weight: bold; + border-radius: 2px; +} +#trace_content .time { + float: right; +} +#trace_content .total_duration { + font-weight: bold; +} diff -r a6c7bf07badb -r 701a5cf6b067 static/lf3.less --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/lf3.less Thu Jul 10 01:19:48 2014 +0200 @@ -0,0 +1,1935 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* end reset */ + + +/* color, fonts, gaps and border radius settings */ + +@body-bg-color: #397ab6; +@body-color: #fff; +@footer-bg-color: #000; +@footer-color: #fff; +@page-bg-color: #ddd; +@mobile-bg-color: #255078; +@head-bg-color: #000; +@head-color: #fff; +@head-second-color: #0e0; +@head-link-color: #fff; +@main-bg-color: #fff; +@main-color: #000; +@main-second-color: #444; +@main-event-color: #070; +@main-negative-event-color: #a00; +@main-head-bg-color: #fff; +@main-head-color: #000; +@main-link-color: #227; +@main-seperator-color: #aaa; +@main-highlight-bg-color: #e7f0ff; +@main-supported-bg-color: #fa2; +@main-satisfied-bg-color: #282; +@sidebar-bg-color: #fff; +@sidebar-color: #000; +@sidebar-head-bg-color: @main-head-bg-color; +@sidebar-head-color: @main-head-color; +@sidebar-link-color: #227; +@sidebar-hr-color: #777; +@disabled-color: #777; +@admitted-color: #0a0; +@not-admitted-color: #a00; + +@delegation-bg-color: #fff; +@delegation-color: #000; +@delegation-active-border-color: #f80; + +@must-bg-color: #0c0; +@must-color: #fff; +@should-bg-color: #4a4; +@should-color: #fff; +@shouldnot-bg-color: #a44; +@shouldnot-color: #fff; +@mustnot-bg-color: #c00; +@mustnot-color: #fff; + +@implemented-bg-color: #0c0; +@implemented-color: #fff; +@notimplemented-bg-color: #c00; +@notimplemented-color: #fff; + +@font: sans-serif; +@size-normal: 10pt; +@size-big: 12pt; +@line-height: 125%; + + + +@logo-font: bold @size-normal e('/') 100% @font; +@instance-font: normal @size-normal e('/') 100% @font; +@mobile-logo-font: bold @size-big e('/') @line-height @font; +@mobile-instance-font: normal @size-normal e('/') 100% @font; + +@title-font: bold @size-big e('/') @line-height @font; + +@main-font: normal @size-normal e('/') @line-height @font; +@event-font: bold @size-normal e('/') @line-height @font; + +@tabs-font: normal @size-normal e('/') @line-height @font; +@tabs-active-font: bold @size-big e('/') @line-height @font; + +@filter-font: normal @size-normal e('/') 150% @font; +@filter-active-font: bold @size-normal e('/') 150% @font; + +@subfilter-font: @filter-font; +@subfilter-active-font: @filter-active-font; + +@head1-font: bold @size-big e('/') @line-height @font; +@head2-font: normal @size-big e('/') @line-height @font; +@head3-font: bold @size-normal e('/') @line-height @font; + +@btn-font: bold @size-normal e('/') @line-height @font; + +@usertext-font: normal @size-normal e('/') @line-height @font; +@usertext-italic-font: italic @size-normal e('/') @line-height @font; +@usertext-bold-font: normal @size-normal e('/') @line-height @font; + + + +@main-width: 70%; + +@pad: 9px; +@grid: 12pt; + +@paragraph-margin: 1.5ex; + +@border-radius: 2px; +@btn-border-radius: 5px; + +.list-style { + list-style: disc; + padding-left: 20px; +} + +@micro-avatar-size: 24px; + +/* + * basic font settings + */ + +html { + overflow-y: scroll; +} + +body { + font: @main-font; + background-color: @body-bg-color; + //background-image: url( "back2.png" ); + color: @main-color; + background-attachment: fixed; +} + +.page { + background-image: url( "back50.png" ); + max-width: 1240px; + border-radius: 0 0 @border-radius @border-radius; + margin: 0 auto; + margin-bottom: 40px; +} + +/* + * messages + */ + +.slot_notice, +.slot_warning, +.slot_error { + font: @head1-font; + padding: @grid; +} + +.slot_motd { + background-color: #ccc; + padding: @grid; +} + +.slot_notice { + background-color: #0c0; + color: #fff; +} + +.slot_warning { + background-color: #f80; + color: #000; +} + +.slot_error { + background-color: #c00; + color: #fff; +} + +/* + * global styles + */ + +/* headlines */ +h1 { + font: @head1-font; + margin-bottom: 1ex; +} + +h1:last-child { + margin-bottom: 0; +} + +h2 { + font: @head2-font; +} + +h3 { + font: @head3-font; +} + +h1:first-child, +h2:first-child, +h3:first-child { + margin-top: 0; +} + +.right { + float: right; +} + +.left { + float: left; + margin-right: @pad; +} + +/* paragraphs */ +p { + margin-bottom: @paragraph-margin; +} + +p:last-child { + margin-bottom: 0; +} + +/* lists */ +ul.ul { + margin-left: @pad; + margin-bottom: @paragraph-margin; + .list-style; + li { + margin: @pad/3 0; + } + + li:last-child { + margin-bottom: 0; + } +} + +ul.ul:last-child { + margin-bottom: 0; +} + + +/* tables */ + +table { + + td { + + padding: 0.3ex 0.3em; + + } + +} + +/* links */ + +a { + color: @main-link-color; +} + +a.disabled { + color: @disabled-color; + cursor: default; +} + +/* formulars */ +form.inline { + display: inline; + div { + display: inline; + } +} + +img { + vertical-align: middle; +} + + +.icon16 { + width: 16px; + height: 16px; +} + +.icon24 { + width: 24px; + height: 24px; +} +.icon32 { + width: 32px; + height: 32px; +} +.icon48 { + width: 48px; + height: 48px; +} + + +img.star { + width: 24px; + height: 24px; +} + +/* + * Avatars + */ + +.microAvatar { + text-wrap: nowrap; +} + +.microAvatar img, +img.micro_avatar { + vertical-align: middle; + border-radius: 2px; + width: @micro-avatar-size; + height: @micro-avatar-size; +} + +img.micro_avatar.highlighted { + margin: 0; + border: 2px solid @delegation-active-border-color; +} + + +/* + * delegation info + */ + +.vote_info, +.delegation_info { + white-space: nowrap; + float: right; + text-decoration: none; + img { + vertical-align: middle; + } + margin: -2px; +} + +.delegation_info img { + border-radius: @border-radius; + margin: 2px; +} + +.delegation_info.suspended { + opacity: 0.3; +} + +.slot_title .delegation_info.suspended { + opacity: 1; +} + +/* + * generic attributes + */ + +.hide { + display: none; +} +.head_outer { + background-color: @head-bg-color; + color: @head-color; + overflow: auto; + margin: 0 auto; + max-width: 1240px; +} +.head { + padding: 0.3ex 0; + margin: 0 @grid; + a { + color: @head-link-color; + } + + /* + * the logo and instance name + */ + .logo { + display: block; + padding: @pad 0; + text-decoration: none; + font: @logo-font; + + .liquid { + color: @head-color; + } + + .feedback { + color: @head-second-color; + } + .instanceName { + font: @instance-font; + padding-top: @pad; + } + } + .logo:hover { + text-decoration: underline; + } + + + + .notifications { + margin-left: 0.6em; + text-decoration: none; + + .count { + background-color: #f00; + color: #000; + padding: 0.2ex 0.25em; + border-radius: 1ex; + vertical-align: top; + } + + .icon { + width: 24px; + height: 24px; + } + } + + /* + * navigation bar + */ + .nav { + float: right; + padding-top: @pad - 3px; + + ul, > ul > li:first-child { + display: inline; + } + + input[name=q] { + width: 12em; + border-radius: @border-radius; + padding: 2px; + background-color: @head-bg-color; + color: @head-color; + border: 1px solid @body-bg-color; + margin-right: 0.6em; + } + input[name=q]:focus { + outline: 2px solid @body-bg-color; + } + + #member_menu a span { + margin-left: 5px; + } + + } + +} + +/* + * title + */ +.slot_title { + + padding-left: @grid; + padding-right: @grid; + font: @title-font; + color: @body-color; + padding-top: @grid; + + a { + color: @body-color; + display: inline-block; + } + + a.home { + margin-right: 4px; + } + + a.delegation_info { + margin-right: 0; + } + + .initiative, + a .label { + display: none; + } + + .delegation_info { + background-color: @main-bg-color; + color: @main-color; + border-radius: @border-radius; + padding-right: 3px; + margin-bottom: @grid; + a { + color: @main-color; + } + } +} + +.content { + clear: both; + margin: 0 @grid; + margin-top: @grid; +} + +/* + * the sidebar + */ + +.sidebar { + float: right; + width: 100% - @main-width; +} + +.sidebarSection { + background-color: @sidebar-bg-color; + border-radius: @border-radius; + color: @sidebar-color; + margin-bottom: @grid; + padding: 0; + + .sidebarHead { + padding: @pad @pad @pad / 2 @pad; + background: @sidebar-head-bg-color; + color: @sidebar-head-color; + + a { + color: @sidebar-head-color; + } + min-height: 20px; + + .icon24 { + margin-top: -@pad/2.5; + } + } + + .sidebarRow { + clear: right; + display: block; + border-top: 1px solid @main-seperator-color; + padding: @pad/2 @pad; + min-height: 20px; + } + .sidebarRow.highlighted { + background-color: @main-highlight-bg-color; + } + + .sidebarRow.sidebarRowNarrow { + padding: @pad / 4 @pad; + } + + .sidebarRow.moreLink { + min-height: 0; + } + + h1, h1 a, + h2, h2 a, + h3, h3 a { + color: @sidebar-head-color; + } + + a { + color: @sidebar-link-color; + } + + .areas { + .whenfolded { + display: none; + } + } + + .areas.folded { + .whenunfolded { + display: none; + } + .whenfolded { + display: block; + } + .disabled { + display: none; + } + } + + + a.issue { + font: @head1-font; + color: @main-color; + } + + ul.initiatives { + li { + padding: @pad/2 @pad; + .bargraph { + display: block; + } + .supporterCount { + white-space: nowrap; + } + border-top: 1px solid @main-seperator-color; + } + .revoked .initiative_name { + text-decoration: line-through; + } + + li.highlighted { + background-color: @main-highlight-bg-color; + } + li.highlighted:last-child{ + border-radius: 0 0 @border-radius @border-radius; + } + } + + .supporters { + line-height: @micro-avatar-size * 1.2; + } + + .supportCount { + color: #00c000; + font: @head1-font; + float: right; + } + + .member_list { + + .member_thumb { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + img.member_image { + width: 24px; + height: 24px; + vertical-align: middle; + margin-right: 0.2em; + } + + } + + .member_thumb.in_delegation_chain { + font-weight: bold; + } + } + + + > div { + position: relative; + } + + > div:first-child { + margin-top: 0; + border-radius: @border-radius @border-radius 0 0; + } + + > div:last-child { + border-radius: 0 0 @border-radius @border-radius; + } + + > div:last-child:first-child { + border-radius: @border-radius; + } + + + a.unit { + font: @head2-font; + } + + a.area { + margin-left: 25px; + display: block; + } + + .star { + float: left; + } + + .delegation_info { + margin-top: -@pad/2.5; + margin-bottom: 1px; + } +} + +.admitted_info h1 { + color: @admitted-color; +} + +.not_admitted_info, .revoked_info { + h1 { + color: @not-admitted-color; + } +} + +.admitted_info, +.not_admitted_info { + + .initiative_pie { + float: right; + } + + table { + tr { + th { + text-align: left; + } + td { + text-align: right; + padding: 0.3ex 0.4em; + } + } + } +} + + + + +/* + * main area + */ + +.main_outer { + width: @main-width; +} + + +.main { + + clear: left; + margin-right: @grid; + border-radius: @border-radius; + + .section { + + .sectionHead, .sectionRow { + background-color: @main-bg-color; + overflow: auto; + padding: @pad; + } + + .sectionHead { + background-color: @main-head-bg-color; + color: @main-head-color; + margin-top: @grid; + border-radius: @border-radius @border-radius 0 0; + } + + .sectionHead:first-child { + margin-top: 0; + } + + .sectionHead:last-child { + border-radius: @border-radius; + } + + + .sectionRow { + margin-top: 4px; + } + + .sectionRow:last-child { + border-radius: 0 0 @border-radius @border-radius; + margin-bottom: @grid; + } + + + } + + .ui_tabs_links { + } + + > h1 { + border-bottom: 1px solid @main-seperator-color; + padding: @pad; + } + + /* + * tabs und filter + */ + + .ui_filter { + .ui_filter_head { + background: @main-head-bg-color; + color: @main-head-color; + padding: 0 @pad @pad @pad; + vertical-align: middle; + a { + white-space: nowrap; + font: @filter-font; + margin-right: 0.5em; + } + a.active { + font: @filter-active-font; + text-decoration: none; + color: @main-head-color; + } + select { + background: @main-bg-color; + color: @main-second-color; + font: @filter-font; + border: none; + padding: 0; + margin: 0; + + option { + color: @main-color; + } + option:first-child, + option[value="interest_direct"], + option[value="interest_delegated"], + option[value="support_direct"], + option[value="support_delegated"], + option[value="potential_support_direct"], + option[value="potential_support_delegated"] { + color: @main-second-color; + } + } + select.active { + color: @main-color; + } + } + .ui_filter_head:first-child { + border-radius: @border-radius @border-radius 0 0; + padding-top: @pad; + } + .ui_filter_head.filter_filter { + padding-top: @pad; + } + + .ui_filter_head.filter_mode { + padding-top: @pad; + margin-bottom: 0; + padding-bottom: 0; + } + .ui_filter_head.subfilter { + a { + font: @subfilter-font; + } + a.active { + font: @subfilter-active-font; + } + } + } + + .filter { + float: right; + } + + .delegation_info.suspended { + margin: 1ex -2px -2px -2px; + } + + + .issues { + .state_info { + font: @event-font; + color: @main-event-color; + } + .state_info.negative { + color: @main-negative-event-color; + } + } + + ul.initiatives { + li { + margin-top: 1ex; + + .bargraph { + float: left; + margin-top: 5px; + margin-right: 0.5em; + } + + .initiative_name { + display: block; + margin-left: 110px; + } + + .rank1 .initiative_name { + margin-left: 0; + } + + .revoked .initiative_name { + text-decoration: line-through; + } + + } + + li:first-child { + margin-top: 0; + clear: none; + } + + } + + .events .event ul.initiatives li .initiative_name { + margin-left: 0; + } + + .member_photo { + float: right; + } + + .member_thumb.in_delegation_chain { + font-weight: bold; + } + + + + /* + * initiative + */ + + + .support { + color: #aaa; + line-height: 80%; + float: right; + width: 102px; + } + + .initiativeInfo { + font-family: @main-font; + line-height: @micro-avatar-size; + overflow: auto; + + .support { + margin-top: 1ex; + float: left; + width: auto; + } + + .mySupport { + line-height: 125%; + min-width: 12em; + text-align: right; + } + + .initiators { + margin-top: 1.5ex; + margin-bottom: -1ex; + float: left; + } + + .links { + margin-top: 1.5ex; + margin-bottom: -1ex; + float: right; + clear: right; + } + + .initiator_links { + clear: right; + } + + } + + .issueInfo { + .links { + margin-top: 1.5ex; + margin-bottom: -1ex; + float: right; + clear: both; + } + } + + .draft_updated_info { + color: @main-event-color; + + .info { + font: @head3-font; + } + } + + /* the draft */ + .draft { + font: @usertext-font; + + ul { + margin-left: 1em; + margin-bottom: @paragraph-margin; + list-style: square; + padding-left: 1em; + } + + h1 { + font: @usertext-italic-font; + font-size: 125%; + border-bottom: 1px solid @main-second-color; + margin-bottom: 1ex; + } + + h2 { + font: @usertext-bold-font; + font-size: 125%; + } + + h3 { + font: @usertext-font; + font-size: 125%; + } + + h4 { + font: @usertext-bold-font; + } + + hr { + border: none; + border-top: 1px solid @main-color; + } + + b, strong { + font: @usertext-italic-font; + } + + i, em { + //font-style: italic; + font: @usertext-bold-font; + } + } + + form, .form { + margin: 0; + padding: 0; + + .ui_field_label { + display: inline-block; + width: 25%; + margin: 0; + padding: 0; + text-align: right; + margin-bottom: @pad; + padding-right: 0.5%; + vertical-align: top; + color: @main-second-color; + } + + input[type=text], + input[type=password], + select, + textarea { + vertical-align: top; + width: 73%; + margin: 0; + padding: 3px; + border: 1px solid @main-second-color; + font: @head3-font; + margin-bottom: @pad; + } + + input:focus { + outline: 2px solid @body-bg-color; + } + + + + .actions { + margin-left: 26%; + } + + } + + form.wide { + input[type=text], + input[type=password], + select, + textarea { + width: 100%; + } + + } + +} + +.issues, .events { + + .event { + + .initiative_pie { + clear: right; + float: right; + } + + ul.initiatives { + + .initiative_info_left { + display: inline; + margin-right: 0.5em; + } + + .initiative_info_right { + float: right; + + .bargraph { + float: right; + margin-left: 0.5em; + } + } + + .result { + color: @main-second-color; + margin-top: 0.5ex; + } + + h3 { + margin-top: 1ex; + margin-bottom: 0; + } + + a.initiative { + font: @head3-font; + } + } + + .event_info { + font: @event-font; + color: @main-event-color; + margin-top: 0.66ex; + margin-bottom: 1ex; + } + + .event_info:last-child { + margin-bottom: 0; + } + + .event_info.negative { + color: @main-negative-event-color; + } + + .event_time { + font: @main-font; + color: @main-second-color; + } + } + + .event:hover { + .event_time { + visibility: visible; + } + ul.initiatives { + div { + visibility: visible; + } + } + } + .issue_context { + line-height: 24px; + margin-bottom: 0.66ex; + .unit { + background-color: #777; + color: #fff; + padding: 1px 3px; + border-radius: @border-radius; + text-decoration: none; + } + .area { + background-color: #ddd; + color: #000; + padding: 1px 3px; + border-radius: @border-radius; + text-decoration: none; + } + } + .issue_info { + .issue { + font: @head3-font; + color: @main-color; + } + } + img.star { + vertical-align: middle; + float: right; + margin-left: 0.5em; + } + + .draft_preview { + } + + .event.suggestion { + + ul.initiatives li { + + margin-top: 0; + margin-bottom: 1ex; + + a { + + font: @main-font; + } + + } + + .suggestion { + + font: @head3-font; + overflow: hidden; + text-overflow: ellipsis; + } + + } + +} + +.suggestions { + + .suggestion { + + .opinion { + float: right; + + .must { + background-color: @must-bg-color; + color: @must-color + } + .should { + background-color: @should-bg-color; + color: @should-color + } + .shouldnot { + background-color: @shouldnot-bg-color; + color: @shouldnot-color + } + .mustnot { + background-color: @mustnot-bg-color; + color: @mustnot-color + } + .implemented { + background-color: @implemented-bg-color; + color: @implemented-color + } + .notimplemented { + background-color: @notimplemented-bg-color; + color: @notimplemented-color + } + + } + + .suggestion-rating { + float: right; + } + .suggestion-text { + margin-top: @pad; + font: @usertext-font; + overflow: hidden; + text-overflow: ellipsis; + position: relative; + z-index: 10; + } + + .suggestion-more { + display: none; + } + + .suggestion-less { + display: none; + } + + .suggestionHead { + overflow: hidden; + text-overflow: ellipsis; + } + + .rating { + display: none; + padding: @pad/2 0; + .active-plus2 { + background-color: @must-bg-color;; + color: @must-color;; + } + .active-plus1 { + background-color: @should-bg-color; + color: @should-color; + } + .active-minus1 { + background-color: @shouldnot-bg-color; + color: @shouldnot-color; + } + .active-minus2 { + background-color: @mustnot-bg-color; + color: @mustnot-color; + } + .active-notfulfilled { + background-color: #faa; + } + .active-fulfilled { + background-color: #afa; + } + } + } + + .suggestion.rateable { + .suggestion-more { + display: block; + } + } + + .suggestion.rateable.unfolded { + .rating { + border-top: 3px solid @body-bg-color; + } + } + + .suggestion.folded { + .suggestion-more { + display: block; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + box-shadow: inset 0 -12ex 10ex -5ex #fff; + padding-top: 5ex; + } + } + + .suggestion.unfolded { + .suggestion-more { + display: none; + } + .rating { + display: block; + } + .suggestion-less { + margin-top: 1ex; + display: block; + } + } + + .suggestion.highlighted { + background-color: @main-highlight-bg-color; + + .suggestion-more { + box-shadow: inset 0 -12ex 10ex -5ex @main-highlight-bg-color; + } + + } + +} + +li.raw { + list-style: none; + padding: 0; + margin: 0 !important; +} + + +.satisfiedSupporterCount { + color: #070; +} +.potentialSupporterCount { + color: #960; +} + +.bargraph { + display: inline-block; + vertical-align: top; + height: 9px; + + div { + margin: 0; + padding: 0; + display: inline-block; + height: 9px; + } + +} + +.diff { + .diff_added { + background-color: #cfc; + } + + .diff_removed { + text-decoration: line-through; + background-color: #fcc; + } +} + +.btn, .ui_paginate_foot a { + text-decoration: none; + min-width: 2em; + text-align: center; + display: inline-block; + border-radius: @btn-border-radius; + border: none; + font: @btn-font; + background-color: #999; + color: #fff !important; + margin-bottom: 5px; +} + +.btn { + padding: 1ex 1em; +} + + + +.ui_paginate_foot a { + padding: 0.5ex 0.5em; + background-color: #eee; + color: 000 !important; +} + +.ui_paginate_foot a.active { + background-color: #666; + color: #fff !important; +} + +.btn-default { + background-color: #47a; + color: #fff !important; +} + +.btn:hover, .btn:focus, .ui_paginate_foot a:hover, .ui_paginate_foot a:focus { + background-color: #0a0; + color: #fff !important; + cursor: pointer; +} + +.btn-dangerous:hover { + background-color: #c00; + color: #fff !important; +} + +.btn-link { + font: @main-font; + background-color: @main-bg-color; + color: @main-link-color; + border: none; + padding: 0; + margin: 0; + text-decoration: underline; + cursor: pointer; +} + +/************************************************************************* + * Voting + */ + +.main .section #voting_form .sectionRow:last-child { + border-radius: 0; + margin-bottom: 0; +} + +#voting { + background: #ddd; + padding: @pad; + margin-top: 4px; + position: relative; + margin-bottom: 2ex; + + .approval, + .abstention, + .disapproval { + border: 2px black solid; + margin-bottom: 2ex; + padding: 1ex; + padding-bottom: 2ex; + border-radius: @border-radius; + } + + .disapproval { + margin-bottom: 2ex; + } + + .approval { + background-color: #9f9; + + .movable { + background-color: #dfd; + } + } + + .abstention { + background-color: #ccc; + + .movable { + background-color: #f2f2f2; + } + } + + .disapproval { + background-color: #f88; + + .movable { + background-color: #fbb; + } + } + + .movable { + position: relative; + border: 1px black solid; + margin-top: 1ex; + padding: 0.5ex; + border-radius: @border-radius; + } + + .voting_form_active { + .movable { + cursor: pointer; + vertical-align: middle; + cursor: move; + } + + .clickable { + cursor: auto; + } + + a.clickable { + cursor: pointer; + } + } +} + + +/* + * footer + */ + +.footer { + text-align: center; + color: @footer-color; + background-color: @footer-bg-color; + padding: @pad 0; + border: 1px solid #000; + border-top: none; + + a { + color: @body-color; + } +} + + +.ui_paginate_head { + display: none; +} + +.ui_paginate_foot { + line-height: 180%; +} + + +.swiper_tabs { + display: none; +} + +#swiper_info { + display: none; +} + +.nav .searchLink { + display: none; +} + + +@media (max-width: 767px) { + +html { + + body { + margin: 0; + background: @mobile-bg-color; + + .head { + margin: @grid/2; + padding: 0; + + .logo { + display: block; + padding: 0; + + .liquid, .feedback { + font: @mobile-logo-font; + } + + .instanceName { + font: @mobile-instance-font; + display: block; + margin-left: 0; + } + } + .nav { + padding: 0; + } + } + + .initiativeInfo h1 { + display: none; + } + + .slot_title { + + font: @head2-font; + padding: 0; + margin: 0 @grid/2; + + .spacer { + display: none; + } + + .unit, .area, .issue, .initiative, .member { + display: block; + margin-right: 0; + padding: 4px 0; + border-radius: @border-radius; + overflow: auto; + } + + .unit:before, .area:before, .issue:before, .initiative:before, .member:before { + content: "↳"; + position: relative; + top: -2px; + } + + .area { + margin-left: 10px; + } + .issue { + margin-left: 10px * 2; + } + .initiative { + margin-left: 10px * 3; + } + + a:last-child, .issue:last-child, .area:last-child, .unit:last-child, .initiative:last-child { + margin-bottom: @grid/2; + } + + .unit, .initiative, .issue, .area { + a { + margin-bottom: 0; + display: inline; + } + } + + a.home { + display: none; + } + + .weight { + float: right; + margin: 0; + } + + .delegation_info { + float: right; + display: block; + margin-top: -10px; + } + a .label { + display: inline; + } + .star { + float: right; + margin-left: 0.5em; + margin-top: -@pad/2; + margin-bottom: -@pad/2; + } + } + + .slot_title > span > *:last-child { + font: @head1-font; + } + + + .page { + background: none; + margin: 0; + box-shadow: none; + } + + .nav #member_menu .text { + display: none; + } + + .nav form.search { + display: none; + } + + .nav .notifications, + .nav .searchLink, + .nav #member_menu a { + vertical-align: middle; + display: inline-block; + height: 48px; + min-width: 35px; + text-align: center; + background-color: #000; + border: 1px solid #777; + border-radius: @border-radius; + img { + margin: 0; + width: 48px; + height: 48px; + } + margin: 0; + } + + .nav .notifications { + padding: 12px 2px; + height: 24px; + } + + .nav #member_menu a :last-child { + display: none; + } + + .notifications span { + margin-left: -5px; + } + + .swiper_tabs { + clear: both; + display: block; + overflow: auto; + margin: @grid/2; + + div { + display: block; + float: left; + width: 33.333%; + + a { + padding: 8px 0; + display: block; + text-align: center; + background-color: #eee; + } + + a.active { + background-color: #abe; + } + } + div:first-child a { + border-radius: @border-radius 0 0 @border-radius; + } + + div:last-child a { + border-radius: 0 @border-radius @border-radius 0; + } + } + + #swiper_info.active { + display: block; + font: @head3-font; + z-index: 1; + text-align: center; + width: 100%; + background-color: @mobile-bg-color; + color: @body-color; + } + + .sidebarSection { + margin: 0 @grid/2 @grid/2 @grid/2; + } + + .main, .extra > .section { + clear: none; + float: none; + width: auto; + margin: 0 @grid/2 @grid/2 @grid/2; + .section .sectionRow:last-child { + margin-bottom: @grid/2; + } + + } + + .ui_filter_head.filter_mode { + float: none !important; + background: @main-bg-color !important; + text-align: left !important; + border-radius: @border-radius; + margin-bottom: @grid/2 !important; + } + + .member_photo { + text-align: center; + margin-bottom: 2ex; + .member_image_photo { + max-width: 600px; + } + } + + #trace_content { + margin: @grid/2 0; + border-radius: 0; + + ul { + li { + .trace_head { + padding: 6px 5px; + } + } + ul { + padding: 5px 2px; + } + } + } + + } +} } + +.textCenter { + text-align: center; +} + +a.initiative { + text-decoration: none; + border-bottom: 1px solid #66c; +} + +a.initiative:hover { + border-bottom: 1px solid #007; +} + + + +#trace_content { + margin: @grid; + padding: @pad; + border-radius: @border-radius; + background-color: @main-bg-color; + + #system_error { + font-family: monospace; + } + + ul { + li { + margin-top: 10px; + .trace_head { + padding: 3px 5px; + border-radius: @border-radius @border-radius 0 0; + } + .trace_head:last-child { + border-radius: @border-radius; + } + ul { + border-radius: 0 0 @border-radius @border-radius; + } + } + li:first-child { + margin-top: 0; + } + ul { + padding: 10px; + } + } + + .trace_config > ul { + background-color: #eee; + border: 1px solid #ccc; + } + .trace_config > .trace_head { + background-color: #ccc; + color: #000; + } + .trace_request > ul { + background-color: #afa; + } + .trace_request > .trace_head { + background-color: #0c0; + } + .trace_filter > ul { + background-color: #ccf; + border: 1px solid #00c; + border-top: none; + } + .trace_filter > .trace_head { + background-color: #00c; + color: #fff; + } + .trace_view > ul { + background-color: #cfc; + border: 1px solid #0c0; + border-top: none; + } + .trace_view > .trace_head { + background-color: #0c0; + color: #000; + } + .trace_action_neutral > ul { + background-color: #ffa; + border: 1px solid #fe0; + } + .trace_action_neutral > .trace_head { + background-color: #fe0; + color: #000; + } + .trace_sql { + background-color: #fff; + padding: 2px 4px; + margin-top: 8px; + } + .trace_error { + background-color: #faa; + color: #000; + font-weight: bold; + border: 1px solid #c00; + } + .trace_exectime { + background-color: #ccc; + font-weight: bold; + border-radius: @border-radius; + } + + .time { + float: right; + } + + .total_duration { + font-weight: bold; + } + +} \ No newline at end of file diff -r a6c7bf07badb -r 701a5cf6b067 static/star.png Binary file static/star.png has changed diff -r a6c7bf07badb -r 701a5cf6b067 static/style.css --- a/static/style.css Thu Jul 10 01:02:43 2014 +0200 +++ b/static/style.css Thu Jul 10 01:19:48 2014 +0200 @@ -139,6 +139,10 @@ border-radius: 4px; } +.btn-default { + +} + /************************************************************************* * Notices, warnings and errors */ @@ -816,6 +820,11 @@ margin-bottom: 0; } +.vertical .actions { + margin-left: 33%; +} + + #voting_form input[type=submit], .login input[type=submit], .vertical input[type=submit] { diff -r a6c7bf07badb -r 701a5cf6b067 utils/optparse.lua --- a/utils/optparse.lua Thu Jul 10 01:02:43 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ --- Lua command line option parser. --- Interface based on Pythons optparse. --- http://docs.python.org/lib/module-optparse.html --- (c) 2008 David Manura, Licensed under the same terms as Lua (MIT license) --- --- To be used like this: --- t={usage="", version=""} --- op=OptionParser(t) --- op=add_option{"", action=, dest=, help=""} --- --- with : --- the option string to be used (can be anything, if one letter opt, then should be -x val, more letters: -xy=val ) --- one of --- - store: store in options as key, val --- - store_true: stores key, true --- - store_false: stores key, false --- is the key under which the option is saved --- --- options,args = op.parse_args() --- --- now options is the table of options (key, val) and args is the table with non-option arguments. --- You can use op.fail(message) for failing and op.print_help() for printing the usage as you like. - ---module('utils.optparse') - -local function OptionParser(t) - local usage = t.usage - local version = t.version - local commands = t.commands - - local o = {} - local option_descriptions = {} - local option_of = {} - - function o.fail(s) -- extension - io.stderr:write(s .. '\n') - os.exit(1) - end - - function o.add_option(optdesc) - option_descriptions[#option_descriptions+1] = optdesc - for _,v in pairs(optdesc) do - option_of[v] = optdesc - end - end - function o.parse_args() - -- expand options (e.g. "--input=file" -> "--input", "file") - local arg = {unpack(arg)} - for i=#arg,1,-1 do local v = arg[i] - local flag, val = v:match('^(%-%-%w+)=(.*)') - if flag then - arg[i] = flag - table.insert(arg, i+1, val) - end - end - - local options = {} - for _,optdesc in ipairs(option_descriptions) do - options[optdesc["dest"]] = optdesc.default - end - local args = {} - local i = 1 - while i <= #arg do local v = arg[i] - local optdesc = option_of[v] - if optdesc then - local action = optdesc.action - local val - if action == 'store' or action == nil then - i = i + 1 - val = arg[i] - if not val then o.fail('option requires an argument ' .. v) end - elseif action == 'store_true' then - val = true - elseif action == 'store_false' then - val = false - end - options[optdesc.dest] = val - else - if v:match('^%-') then o.fail('invalid option ' .. v) end - args[#args+1] = v - end - i = i + 1 - end - if options.help then - o.print_help() - os.exit() - end - if options.version then - io.stdout:write(t.version .. "\n") - os.exit() - end - return options, args - end - - local function flags_str(optdesc) - local sflags = {} - local action = optdesc.action - for _,flag in ipairs(optdesc) do - local sflagend - if action == nil or action == 'store' then - local metavar = optdesc.metavar or optdesc.dest:upper() - sflagend = #flag == 2 and ' ' .. metavar - or '=' .. metavar - else - sflagend = '' - end - sflags[#sflags+1] = flag .. sflagend - end - return table.concat(sflags, ', ') - end - - function o.print_help() - io.stdout:write("Usage: " .. usage:gsub('%%prog', arg[0]) .. "\n") - io.stdout:write("\n") - io.stdout:write("Options:\n") - for _,optdesc in ipairs(option_descriptions) do - io.stdout:write(" " .. flags_str(optdesc) .. - " " .. optdesc.help .. "\n") - end - if commands then - io.stdout:write("\nCommands:\n") - for _,command in ipairs(commands) do - io.stdout:write(" " .. command[1] .. - string.rep(" ", 30-#command[1]) .. - command[2] .. "\n") - end - end - - end - o.add_option{"--help", action="store_true", dest="help", - help="show this help message and exit"} - if t.version then - o.add_option{"--version", action="store_true", dest="version", - help="output version info."} - end - return o -end - -return OptionParser \ No newline at end of file