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)

