Sorry, the earlier patch contained some typos. Here is the corrected 
version.

On Monday, 31 December 2012 05:18:12 UTC+8, Massimo Di Pierro wrote:
>
> Seems like a good idea. What do other think? If the difference is only in 
> the type, could we simply override the value of type using a class variable 
> and use the widget method of the base class?
>
> Massimo
>
> On Sunday, 30 December 2012 12:01:06 UTC-6, Calvin wrote:
>>
>> Hi Massimo
>>
>> Here is a patch which updates the date, time and datetime widget. If this 
>> approach is acceptable, I am happy to provide a patch for the other types 
>> as well.
>>
>> Calvin
>>
>> On Sunday, 30 December 2012 00:50:59 UTC+8, Massimo Di Pierro wrote:
>>>
>>> I think this would be a good idea but somebody should be in charge of 
>>> this. Perhaps we can take this approach for web3py where widgets will have 
>>> a simpler internal design. It will be possible to use web3py widgets in 
>>> web2py.
>>>
>>> Anybody wants to be in charge of this? I can explain more so we can 
>>> discuss options.
>>>
>>> Massimo
>>>
>>>
>>>

-- 



>From 4a4806d78aa18ea109b8c14e425d12cc3ed49071 Mon Sep 17 00:00:00 2001
From: Calvin Sim <[email protected]>
Date: Mon, 31 Dec 2012 01:56:23 +0800
Subject: [PATCH 1/5] updated date, time, datetime widget's type attribute to
 enable more specific inputs with compatible browsers.

---
 gluon/sqlhtml.py |   42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py
index a5827e9..7f4423b 100644
--- a/gluon/sqlhtml.py
+++ b/gluon/sqlhtml.py
@@ -160,16 +160,56 @@ class DecimalWidget(StringWidget):
 class TimeWidget(StringWidget):
     _class = 'time'
 
+    @classmethod
+    def widget(cls, field, value, **attributes):
+        """
+        generates an INPUT time tag.
+
+        see also: :meth:`FormWidget.widget`
+        """
+
+        default = dict(_type='time', value=value)
+        attr = cls._attributes(field, default,
+                               **attributes)
+        return INPUT(**attr)
+
 
 class DateWidget(StringWidget):
     _class = 'date'
 
+    @classmethod
+    def widget(cls, field, value, **attributes):
+        """
+        generates an INPUT date tag.
+
+        see also: :meth:`FormWidget.widget`
+        """
+
+        default = dict(_type='date', value=value)
+        attr = cls._attributes(field, default,
+                               **attributes)
+        return INPUT(**attr)
+
 
 class DatetimeWidget(StringWidget):
     _class = 'datetime'
 
 
-class TextWidget(FormWidget):
+classssmethod
+    def widget(cls, field, value, **attributes):
+        """
+        generates an INPUT datetime tag.
+
+        see also: :meth:`FormWidget.widget`
+        """
+
+        default = dict(_type='datetime', value=value)
+        attr = cls._attributes(field, default,
+                               **attributes)
+        return INPUT(**attr)
+
+
+ TextWidget(FormWidget):
     _class = 'text'
 
     @classmethod
-- 
1.7.10.2 (Apple Git-33)


>From 52c1ba67e33ebdef20268c2e31141cc70185ac3f Mon Sep 17 00:00:00 2001
From: mdipierro <[email protected]>
Date: Sun, 30 Dec 2012 15:16:39 -0600
Subject: [PATCH 2/5] added
 setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh,
 thanks Richard

---
 VERSION                                            |    2 +-
 ...ntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh |  464 ++++++++++++++++++++
 2 files changed, 465 insertions(+), 1 deletion(-)
 create mode 100644 scripts/setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh

diff --git a/VERSION b/VERSION
index 25bf7f5..c532e5e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-Version 2.4.1-alpha.2+timestamp.2012.12.28.16.18.51
+Version 2.4.1-alpha.2+timestamp.2012.12.30.15.15.53
diff --git a/scripts/setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh b/scripts/setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
new file mode 100644
index 0000000..84a0b0f
--- /dev/null
+++ b/scripts/setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
@@ -0,0 +1,464 @@
+#!/bin/bash
+
+# ------------------------------------------------------------------------------
+# Description : Installation and basic configuration of web2py, uWSGI, Redmine,
+#               Unicorn, Nginx and PostgreSQL.
+#       Usage : Copy the script in /home/username and run it as root, you may 
+#               need to allow exectuion (chmod +x). Ex.: 
+#               sudo ./setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
+#        File : setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
+#      Author : Richard V?zina
+#       Email : [email protected]
+#   Copyright : Richard V?zina
+#        Date : ven 28 d?c 2012 13:27:11 EST
+# Disclaimers : This script is provided "as is", without warranty of any kind.
+#     Licence : CC BY-NC 2.5 CA
+# ------------------------------------------------------------------------------
+
+echo 'setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh'
+echo 'Requires Ubuntu = 12.04 (May works with 12.10 not tested) and installs Redmine + Unicorn + Web2py + uWSGI + Nginx + PostgreSQL'
+# Check if user has root privileges
+if [[ $EUID -ne 0 ]]; then
+   echo "You must run the script as root or using sudo"
+   exit 1
+fi
+
+# ------------------------------------------------------------------------------
+# We concentrate here user prompts!!
+# Get Redmine Postgres Database Password
+echo -e "Redmine Postgres Database Password: \c "
+read  REDMINEPASSWORD
+# Get Web2py Admin Password
+echo -e "Web2py Admin Password: \c "
+read  PW
+
+cd ~
+openssl genrsa 1024 > self_signed.key
+chmod 400 self_signed.key
+openssl req -new -x509 -nodes -sha1 -days 1780 -key self_signed.key > self_signed.cert
+openssl x509 -noout -fingerprint -text < self_signed.cert > self_signed.info
+# ------------------------------------------------------------------------------
+
+apt-get update
+apt-get -y upgrade
+apt-get autoremove
+apt-get autoclean
+apt-get -y install postgresql
+apt-get -y install nginx-full
+apt-get -y install build-essential python-dev libxml2-dev python-pip unzip
+apt-get -y install ruby1.9.3 # Ref.: http://askubuntu.com/questions/137485/rails-3-not-using-rvm
+apt-get -y install libpq-dev # Required for gem1.9.3 install pg Ref.: http://stackoverflow.com/questions/6040583/unable-to-install-pg-gem-on-ubuntu-cant-find-the-libpq-fe-h-header
+
+gem1.9.3 install rails --no-rdoc --no-ri # For testing (faster) --no-rdoc --no-ri
+gem1.9.3 install unicorn --no-rdoc --no-ri # For testing (faster) --no-rdoc --no-ri
+gem1.9.3 install pg --no-rdoc --no-ri # For testing (faster) --no-rdoc --no-ri
+cd /opt
+wget http://rubyforge.org/frs/download.php/76627/redmine-2.2.0.tar.gz
+wget http://rubyforge.org/frs/download.php/76628/redmine-2.2.0.tar.gz.md5
+md5sum --check redmine-2.2.0.tar.gz.md5 > redmine_md5_checked_successfully
+if [ -f redmine_md5_checked_successfully ]
+then
+	tar xvfz redmine-2.2.0.tar.gz
+	rm redmine_md5_checked_successfully
+else
+    echo "Redmine md5 check sum failed..."
+    exit 1
+fi
+cd redmine-2.2.0
+bundle install --without development test rmagick sqlite mysql
+mkdir /var/www
+ln -s /opt/redmine-2.2.0/public /var/www/redmine
+chown -R www-data.www-data /var/www
+chown -R www-data.www-data /opt/redmine-2.2.0/public
+# To avoid prompt during execution of the script use psql instead of createuser
+#echo "Enter a postgres redmine user password twice:"
+#createuser -P -S -D -R -l -e redmine
+# createuser switch: -P --pwprompt -S --no-superuser -D --no-createdb  -R --no-createrole -l --login -e --echo
+sudo -u postgres psql -c "CREATE ROLE redmine LOGIN; ALTER ROLE redmine WITH ENCRYPTED PASSWORD '$REDMINEPASSWORD';"
+# createdb wouldn't work without having root password
+#createdb -U postgres -w -E UTF8 -O redmine -e redmine
+# createdb switch: -U username --username=username -w --no-password -E Encoding -O owner --owner=owner -e --echo
+sudo -u postgres psql -c "CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;"
+cd /opt/redmine-2.2.0/config
+# Here we change related to an issue with new rails version as far as I understand
+# Ref1.: http://www.redmine.org/projects/redmine/wiki/HowTo_Install_Redmine_in_a_sub-URI # Preferred solution used
+# Ref2.: http://www.redmine.org/issues/12102 # JS and CSS was not working until I add this line 'RedmineApp::Application.routes.default_scope =  { :path => "/redmine", :shallow_path => "/redmine" }' before 'RedmineApp::Application.initialize!'
+cp environment.rb environment.rb_original # Backup default environment.rb
+sed '/RedmineApp::Application.initialize!/c \RedmineApp::Application.routes.default_scope =  { :path => "/redmine", :shallow_path => "/redmine" }\nRedmineApp::Application.initialize!\nRedmine::Utils::relative_url_root = "/redmine"' environment.rb_original > environment.rb
+# Now we configure Redmine database access
+#nano database.yml
+# paste :
+echo 'production:
+ adapter: postgresql
+ database: redmine
+ host: localhost
+ username: redmine
+ password: "'$REDMINEPASSWORD'"
+ encoding: utf8' > database.yml
+rake generate_secret_token
+RAILS_ENV=production rake db:migrate
+RAILS_ENV=production rake redmine:load_default_data
+mkdir /opt/redmine-2.2.0/tmp/pids 
+#mkdir /opt/redmine-2.2.0/log # if not there
+cd /opt/redmine-2.2.0/config 
+# Create Unicorn specific Redmine config in /opt/redmine-2.2.0/config/unicorn.rb
+echo '#unicorn.rb Starts here
+worker_processes 1
+working_directory "/opt/redmine-2.2.0" # needs to be the correct directory for redmine
+
+# This loads the application in the master process before forking
+# worker processes
+# Read more about it here:
+# http://unicorn.bogomips.org/Unicorn/Configurator.html
+preload_app true
+timeout 45
+
+# This is where we specify the socket.
+# We will point the upstream Nginx module to this socket later on
+listen "/tmp/unicorn_rails.socket", :backlog => 64 #directory structure needs to be created. 
+pid "/opt/redmine-2.2.0/tmp/pids/unicorn_rails.pid" # make sure this points to a valid directory. Make sure it is named the same as the real process name in order to allow init.d script start-stop-daemon command to kill unicorn process properly 
+
+# Set the path of the log files inside the log folder of the testapp
+stderr_path "/opt/redmine-2.2.0/log/unicorn_rails.stderr.log"
+stdout_path "/opt/redmine-2.2.0/log/unicorn_rails.stdout.log"
+
+before_fork do |server, worker|
+# This option works in together with preload_app true setting
+# What is does is prevent the master process from holding
+# the database connection
+defined?(ActiveRecord::Base) and
+ActiveRecord::Base.connection.disconnect!
+end
+
+after_fork do |server, worker|
+# Here we are establishing the connection after forking worker
+# processes
+defined?(ActiveRecord::Base) and
+ActiveRecord::Base.establish_connection
+# change below if your redmine instance is running differently
+worker.user('\''www-data'\'', '\''www-data'\'') if Process.euid == 0
+end
+#unicorn.rb Ends here' > unicorn.rb
+chown www-data:www-data unicorn.rb 
+chown -R www-data:www-data /opt/redmine-2.2.0/tmp
+mkdir /etc/unicorn
+# Set some config for Unicorn in /etc/unicorn/redmine
+echo 'RAILS_ROOT=/opt/redmine-2
+RAILS_ENV=production' > /etc/unicorn/redmine
+# Create a Unicorn Redmine start script in /etc/init.d/redmine
+echo '#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          redmine
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: redmine initscript
+# Description:       This script startup unicorn server and redmine and should
+#                    be placed in /etc/init.d.
+### END INIT INFO
+
+# ------------------------------------------------------------------------------
+# Author: Richard V?zina <[email protected]>
+# Base on Ubuntu 12.04 : /etc/init.d/skeleton
+# ven 21 d?c 2012 11:08:31 EST 
+# ------------------------------------------------------------------------------
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+APP=/opt/redmine-2.2.0/
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="Unicorn and Redmine"
+NAME=unicorn_rails
+DAEMON=/usr/local/bin/$NAME
+DAEMON_ARGS=" -E production -c $APP/config/unicorn.rb -D"
+PIDFILE=/opt/redmine-2.2.0/tmp/pids/$NAME.pid
+SCRIPTNAME=/etc/init.d/redmine
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don'\''t delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+       ;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave '\''force-reload'\'' as an alias for '\''restart'\''.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# '\''force-reload'\'' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+	  	# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:' > /etc/init.d/redmine
+chmod +x /etc/init.d/redmine
+# Backup default Nginx site and replace it 
+cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default_original
+rm /etc/nginx/sites-available/default
+# Create configuration file /etc/nginx/sites-available/default
+echo 'upstream unicorn_server { 
+   # This is the socket we configured in unicorn.rb 
+   server unix:/tmp/unicorn_rails.socket 
+   fail_timeout=0; 
+}
+server {
+        listen          80;
+        #return 301 https://192.168.1.126$request_uri; # http://$hostname$request_uri; # idem #http://wiki.nginx.org/Pitfalls#Taxing_Rewrites
+        charset utf-8;
+        server_name     localhost; # $hostname;
+        root /var/www;
+        access_log  /var/log/nginx/yoursite.access.log; 
+        error_log  /var/log/nginx/yoursite.error.log; 
+        #to enable correct use of response.static_version
+        #location ~* /(\w+)/static(?:/_[\d]+\.[\d]+\.[\d]+)?/(.*)$ {
+        #    alias /home/www-data/web2py/applications/$1/static/$2;
+        #    expires max;
+        #}
+        location ~* /(\w+)/static/ {
+            root /home/www-data/web2py/applications/;
+            #remove next comment on production
+            #expires max;
+        }
+        location ~^\/(?!redmine(.*)) {
+            #uwsgi_pass      127.0.0.1:9001;
+            uwsgi_pass      unix:///tmp/web2py.socket;
+            include         uwsgi_params;
+            uwsgi_param     UWSGI_SCHEME $scheme;
+            uwsgi_param     SERVER_SOFTWARE    nginx/$nginx_version;
+        }
+        location / { 
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
+            proxy_set_header Host $http_host; 
+            proxy_redirect off; 
+ 
+            if (!-f $request_filename) { 
+                proxy_pass http://unicorn_server; 
+                break; 
+            } 
+        } 
+}
+server {
+        listen 443 default_server ssl;
+        charset utf-8;
+        server_name     localhost; # $hostname;
+        root /var/www;
+        ssl_certificate         /etc/nginx/ssl/self_signed.cert;
+        ssl_certificate_key     /etc/nginx/ssl/self_signed.key;
+		ssl_prefer_server_ciphers on;
+		ssl_session_cache shared:SSL:10m;
+		ssl_session_timeout 10m;
+		ssl_ciphers ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA;
+		ssl_protocols SSLv3 TLSv1;
+		keepalive_timeout    70;
+        location ~^\/(?!redmine(.*)) {
+            #uwsgi_pass      127.0.0.1:9001;
+            uwsgi_pass      unix:///tmp/web2py.socket;
+            include         uwsgi_params;
+            uwsgi_param     UWSGI_SCHEME $scheme;
+            uwsgi_param     SERVER_SOFTWARE    nginx/$nginx_version;
+        }
+        location / { 
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
+            proxy_set_header Host $http_host; 
+            proxy_redirect off; 
+ 
+            if (!-f $request_filename) { 
+                proxy_pass http://unicorn_server; 
+                break; 
+            } 
+        } 
+
+}' >/etc/nginx/sites-available/default
+
+#ln -s /etc/nginx/sites-available/web2py /etc/nginx/sites-enabled/web2py
+#rm /etc/nginx/sites-enabled/default
+
+# We copy ssl files we previously created
+if [ -f /etc/nginx/ssl ]
+then
+	cp ~/self_signed.* /etc/nginx/ssl/
+	rm ~/self_signed.*
+else
+    mkdir /etc/nginx/ssl
+    cp ~/self_signed.* /etc/nginx/ssl/
+    rm ~/self_signed.*
+fi
+
+pip install --upgrade pip
+PIPPATH=`which pip`
+$PIPPATH install --upgrade uwsgi
+
+# Prepare folders for uwsgi
+sudo mkdir /etc/uwsgi
+sudo mkdir /var/log/uwsgi
+
+# Create configuration file /etc/uwsgi/web2py.xml
+echo '<uwsgi>
+    <socket>/tmp/web2py.socket</socket>
+    <pythonpath>/home/www-data/web2py/</pythonpath>
+    <mount>/=wsgihandler:application</mount>
+    <master/>
+    <processes>4</processes>
+    <harakiri>60</harakiri>
+    <reload-mercy>8</reload-mercy>
+    <cpu-affinity>1</cpu-affinity>
+    <stats>/tmp/stats.socket</stats>
+    <max-requests>2000</max-requests>
+    <limit-as>512</limit-as>
+    <reload-on-as>256</reload-on-as>
+    <reload-on-rss>192</reload-on-rss>
+    <uid>www-data</uid>
+    <gid>www-data</gid>
+    <cron>0 0 -1 -1 -1 python /home/www-data/web2py/web2py.py -Q -S welcome -M -R scripts/sessions2trash.py -A -o</cron>
+    <no-orphans/>
+</uwsgi>' > /etc/uwsgi/web2py.xml
+
+#Create a configuration file for uwsgi in emperor-mode
+#for Upstart in /etc/init/uwsgi-emperor.conf
+echo '# Emperor uWSGI script
+
+description "uWSGI Emperor"
+start on runlevel [2345]
+stop on runlevel [06]
+##
+#remove the comments in the next section to enable static file compression for the welcome app
+#in that case, turn on gzip_static on; on /etc/nginx/nginx.conf
+##
+#pre-start script
+#    python /home/www-data/web2py/web2py.py -S welcome -R scripts/zip_static_files.py
+#    chown -R www-data:www-data /home/www-data/web2py/*
+#end script
+respawn
+exec uwsgi --master --die-on-term --emperor /etc/uwsgi --logto /var/log/uwsgi/uwsgi.log
+' > /etc/init/uwsgi-emperor.conf
+# Install Web2py
+mkdir /home/www-data
+cd /home/www-data
+wget http://web2py.com/examples/static/web2py_src.zip
+unzip web2py_src.zip
+rm web2py_src.zip
+# Download latest version of sessions2trash.py
+wget http://web2py.googlecode.com/hg/scripts/sessions2trash.py -O /home/www-data/web2py/scripts/sessions2trash.py
+chown -R www-data:www-data web2py
+cd /home/www-data/web2py
+sudo -u www-data python -c "from gluon.main import save_password; save_password('$PW',443)"
+/etc/init.d/redmine start
+start uwsgi-emperor
+/etc/init.d/nginx restart
+ufw allow 80 # Or check your firewall configuration
-- 
1.7.10.2 (Apple Git-33)


>From 117a0b9849f1bb47efb265623e7d56a594c7f6fd Mon Sep 17 00:00:00 2001
From: mdipierro <[email protected]>
Date: Mon, 31 Dec 2012 14:38:43 -0600
Subject: [PATCH 3/5] fixed issue 1247 Missing URL for Delete button, thanks
 Boris and Niphlod

---
 VERSION          |    2 +-
 gluon/html.py    |    4 ++--
 gluon/sqlhtml.py |   40 +++++++++++++++++-----------------------
 3 files changed, 20 insertions(+), 26 deletions(-)

diff --git a/VERSION b/VERSION
index c532e5e..4ffd115 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-Version 2.4.1-alpha.2+timestamp.2012.12.30.15.15.53
+Version 2.4.1-alpha.2+timestamp.2012.12.31.14.38.01
diff --git a/gluon/html.py b/gluon/html.py
index 09783e7..e38c4d8 100644
--- a/gluon/html.py
+++ b/gluon/html.py
@@ -1478,9 +1478,9 @@ class A(DIV):
                 (self['component'], self['target'] or '', d)
             self['_href'] = self['_href'] or '#null'
         elif self['callback']:
-            returnfalse = "var e = arguments[0] || window.event; e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation();"
+            returnfalse = "var e = arguments[0] || window.event; e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); e.preventDefault();"
             if d:
-                self['_onclick'] = "if(confirm(w2p_ajax_confirm_message||'Are you sure you want o delete this object?')){ajax('%s',[],'%s');%s};%s" % \
+                self['_onclick'] = "if(confirm(w2p_ajax_confirm_message||'Are you sure you want to delete this object?')){ajax('%s',[],'%s');%s};%s" % \
                     (self['callback'], self['target'] or '', d, returnfalse)
             else:
                 self['_onclick'] = "ajax('%s',[],'%s');%sreturn false" % \
diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py
index a5827e9..f822804 100644
--- a/gluon/sqlhtml.py
+++ b/gluon/sqlhtml.py
@@ -1807,28 +1807,21 @@ class SQLFORM(FORM):
                        buttonurl=url(args=[]), callback=None,
                        delete=None, trap=True):
             if showbuttontext:
-                if callback:
-                    return A(SPAN(_class=ui.get(buttonclass)),
-                             SPAN(T(buttontext), _title=buttontext,
-                                  _class=ui.get('buttontext')),
-                             callback=callback, delete=delete,
-                             _class=trap_class(ui.get('button'), trap))
-                else:
-                    return A(SPAN(_class=ui.get(buttonclass)),
-                             SPAN(T(buttontext), _title=buttontext,
-                                  _class=ui.get('buttontext')),
-                             _href=buttonurl,
-                             _class=trap_class(ui.get('button'), trap))
+                return A(SPAN(_class=ui.get(buttonclass)),
+                         SPAN(T(buttontext), _title=buttontext,
+                              _class=ui.get('buttontext')),
+                         _href=buttonurl,
+                         callback=callback,
+                         delete=delete,
+                         _class=trap_class(ui.get('button'), trap))
             else:
-                if callback:
-                    return A(SPAN(_class=ui.get(buttonclass)),
-                             callback=callback, delete=delete,
-                             _title=buttontext,
-                             _class=trap_class(ui.get('buttontext'), trap))
-                else:
-                    return A(SPAN(_class=ui.get(buttonclass)),
-                             _href=buttonurl, _title=buttontext,
-                             _class=trap_class(ui.get('buttontext'), trap))
+                return A(SPAN(_class=ui.get(buttonclass)),
+                         _href=buttonurl,
+                         callback=callback,
+                         delete=delete,
+                         _title=buttontext,
+                         _class=trap_class(ui.get('buttontext'), trap))
+
         dbset = db(query)
         tablenames = db._adapter.tables(dbset.query)
         if left is not None:
@@ -1948,8 +1941,8 @@ class SQLFORM(FORM):
             table = db[request.args[-2]]
             if ondelete:
                 ondelete(table, request.args[-1])
-            ret = db(table[table._id.name] == request.args[-1]).delete()
-            return ret
+            db(table[table._id.name] == request.args[-1]).delete()
+            redirect(referrer)
 
         exportManager = dict(
             csv_with_hidden_cols=(ExporterCSV, 'CSV (hidden cols)'),
@@ -2293,6 +2286,7 @@ class SQLFORM(FORM):
                     if deletable and (not callable(deletable) or deletable(row)):
                         row_buttons.append(gridbutton(
                             'buttondelete', 'Delete',
+                            url(args=['delete', tablename, id]),
                             callback=url(args=['delete', tablename, id]),
                             delete='tr'))
                     if buttons_placement in ['right', 'both']:
-- 
1.7.10.2 (Apple Git-33)


>From ed42c3e489917c9b78ca9f3ba2032ab38a95b52f Mon Sep 17 00:00:00 2001
From: mdipierro <[email protected]>
Date: Mon, 31 Dec 2012 15:17:55 -0600
Subject: [PATCH 4/5] fixed issue 1246, is_active and left joins

---
 VERSION      |    2 +-
 gluon/dal.py |   16 +++++++++-------
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/VERSION b/VERSION
index 4ffd115..19eb19b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-Version 2.4.1-alpha.2+timestamp.2012.12.31.14.38.01
+Version 2.4.1-alpha.2+timestamp.2012.12.31.15.17.11
diff --git a/gluon/dal.py b/gluon/dal.py
index b4df67e..4dff548 100644
--- a/gluon/dal.py
+++ b/gluon/dal.py
@@ -1291,6 +1291,8 @@ class BaseAdapter(ConnectionPool):
         return '%s AS %s' % (self.expand(first), second)
 
     def ON(self, first, second):
+        if use_common_filters(second):
+            second = self.common_filter(second,[first._tablename])
         return '%s ON %s' % (self.expand(first), self.expand(second))
 
     def INVERT(self, first):
@@ -1466,9 +1468,6 @@ class BaseAdapter(ConnectionPool):
                 if not tablename in tablenames:
                     tablenames.append(tablename)
 
-        if use_common_filters(query):
-            query = self.common_filter(query,tablenames)
-
         if len(tablenames) < 1:
             raise SyntaxError('Set: no tables selected')
         self._colnames = map(self.expand, fields)
@@ -1477,10 +1476,6 @@ class BaseAdapter(ConnectionPool):
                 field = field.st_astext()
             return self.expand(field)
         sql_f = ', '.join(map(geoexpand, fields))
-        if query:
-            sql_w = ' WHERE ' + self.expand(query)
-        else:
-            sql_w = ''
         sql_o = ''
         sql_s = ''
         left = args_get('left', False)
@@ -1530,6 +1525,13 @@ class BaseAdapter(ConnectionPool):
             important_tablenames = joint + joinont + tables_to_merge.keys()
             excluded = [t for t in tablenames
                         if not t in important_tablenames ]
+        else:
+            excluded = tablenames
+
+        if use_common_filters(query):
+            query = self.common_filter(query,excluded)
+        sql_w = ' WHERE ' + self.expand(query) if query else ''
+
         def alias(t):
             return str(self.db[t])
         if inner_join and not left:
-- 
1.7.10.2 (Apple Git-33)


>From 84641c548021e63c7ef0719df007a5d2a68c9369 Mon Sep 17 00:00:00 2001
From: Calvin Sim <[email protected]>
Date: Tue, 1 Jan 2013 22:01:12 +0800
Subject: [PATCH 5/5] Fixed typos in sqlhtml_widgets_update

---
 gluon/sqlhtml.py |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py
index 7949b0d..95d19b9 100644
--- a/gluon/sqlhtml.py
+++ b/gluon/sqlhtml.py
@@ -195,7 +195,7 @@ class DatetimeWidget(StringWidget):
     _class = 'datetime'
 
 
-classssmethod
+    @classmethod
     def widget(cls, field, value, **attributes):
         """
         generates an INPUT datetime tag.
@@ -209,7 +209,7 @@ classssmethod
         return INPUT(**attr)
 
 
- TextWidget(FormWidget):
+class TextWidget(FormWidget):
     _class = 'text'
 
     @classmethod
-- 
1.7.10.2 (Apple Git-33)

Reply via email to