diff options
59 files changed, 1668 insertions, 327 deletions
diff --git a/bin/ec2-rewrite-conf b/bin/ec2-rewrite-conf new file mode 100755 index 000000000..0163ef511 --- /dev/null +++ b/bin/ec2-rewrite-conf @@ -0,0 +1,20 @@ +#!/bin/sh + +# This is a helper script for writing the current EC2 hostname into +# the FixMyStreet configuration file. Its intended usage is for lines +# like these to be added to /etc/rc.local: +# +# su -l -c /home/fms/fixmystreet/bin/ec2-rewrite-conf fms +# /etc/init.d/apache2 restart + +set -e + +BIN_DIR=$(dirname $(readlink -f $0)) +CONF_DIR=$BIN_DIR/../conf + +HOST=`curl -s http://169.254.169.254/latest/meta-data/public-hostname` + +sed -i -r \ + -e "s,^( *BASE_URL:).*,\\1 'http://$HOST'," \ + -e "s,^( *EMAIL_DOMAIN:).*,\\1 '$HOST'," \ + $CONF_DIR/general.yml diff --git a/bin/install-as-user b/bin/install-as-user new file mode 100755 index 000000000..4757090aa --- /dev/null +++ b/bin/install-as-user @@ -0,0 +1,126 @@ +#!/bin/sh + +set -e +set -x + +DEFAULT_SERVER=false +if [ x"$1" = x"--default" ] +then + DEFAULT_SERVER=true + shift +fi + +if [ $# -ne 2 ] +then + cat >&2 <<EOUSAGE +Usage: $0 [--default] <UNIX-USER> <HOST> +--default means to install as the default site for this server, +rather than a virtualhost for HOST. +EOUSAGE + exit 1 +fi + +UNIX_USER="$1" +HOST="$2" +DB_NAME="fixmystreet" + +# Check that the arguments we've been passed are sensible: + +IP_ADDRESS_FOR_HOST="$(dig +short $HOST)" + +if [ x = x"$IP_ADDRESS_FOR_HOST" ] +then + echo "The hostname $HOST didn't resolve to an IP address" + exit 1 +fi + +if ! id "$UNIX_USER" 2> /dev/null > /dev/null +then + echo "The user '$UNIX_USER' didn't exist." + echo "(You should have run \"sudo pre-install-as-root '$UNIX_USER' '$HOST'\" before this.)" + exit 1 +fi + +if [ "$(whoami)" != "$UNIX_USER" ] +then + echo "This script should be run by the user '$UNIX_USER'." + exit 1 +fi + +if [ $DEFAULT_SERVER = true ] +then + FMS_DIRECTORY="/var/www/fixmystreet" +else + FMS_DIRECTORY="/var/www/$HOST" +fi +FMS_REPOSITORY="$FMS_DIRECTORY/fixmystreet" +FMS_LINK_DESTINATION="$HOME/fixmystreet" + +ln -sfn "$FMS_REPOSITORY" $FMS_LINK_DESTINATION +cd "$FMS_REPOSITORY" + +# Add regularly scheduled tasks to cron: + +TEMPORARY_CRONTAB=$(mktemp) + +echo crontab file is $TEMPORARY_CRONTAB + +cp "$FMS_REPOSITORY"/conf/crontab.example "$TEMPORARY_CRONTAB" + +sed -i \ + -e 's,$FMS,'"$FMS_REPOSITORY,g" \ + -e 's,$LOCK_DIR,'"$FMS_DIRECTORY,g" \ + "$TEMPORARY_CRONTAB" + +crontab $TEMPORARY_CRONTAB + +# Install the compass gem locally - it's required for generating the +# CSS: + +export GEM_HOME="$FMS_DIRECTORY/gems" +mkdir -p "$GEM_HOME" +export GEM_PATH= +export PATH="$GEM_HOME/bin:$PATH" + +gem install --no-ri --no-rdoc compass + +# Use compass to generate the CSS, if it doesn't seem to already +# exist: + +if [ ! -f web/cobrands/default/base.css ] +then + bin/make_css +fi + +# Write sensible values into the config file: + +sed -r \ + -e "s,^( *FMS_DB_HOST:).*,\\1 ''," \ + -e "s,^( *FMS_DB_NAME:).*,\\1 '$DB_NAME'," \ + -e "s,^( *FMS_DB_USER:).*,\\1 '$UNIX_USER'," \ + -e "s,^( *BASE_URL:).*,\\1 'http://$HOST'," \ + -e "s,^( *EMAIL_DOMAIN:).*,\\1 '$HOST'," \ + -e "s,^( *CONTACT_EMAIL:).*,\\1 'help@$HOST'," \ + conf/general.yml-example > conf/general.yml + +# Create the database if it doesn't exist: +if ! psql -l | egrep "^ *$DB_NAME *\|" > /dev/null +then + createdb --owner "$UNIX_USER" "$DB_NAME" + echo 'CREATE LANGUAGE plpgsql;' | psql -U "$UNIX_USER" "$DB_NAME" || true + psql -U "$UNIX_USER" "$DB_NAME" < "$FMS_REPOSITORY"/db/schema.sql + psql -U "$UNIX_USER" "$DB_NAME" < "$FMS_REPOSITORY"/db/alert_types.sql + psql -U "$UNIX_USER" "$DB_NAME" < "$FMS_REPOSITORY"/db/generate_secret.sql +fi + +# Install the required Perl modules - this may take a very long time: + +cd "$FMS_REPOSITORY" +bin/install_perl_modules + +# Generate po and mo files (these invocations taken from Kagee's script): + +./bin/cron-wrapper ./bin/make_emptyhomes_po +./bin/cron-wrapper ./bin/make_emptyhomes_welsh_po + +commonlib/bin/gettext-makemo FixMyStreet diff --git a/bin/open311-populate-service-list b/bin/open311-populate-service-list index 33be61af7..99f8502a7 100755 --- a/bin/open311-populate-service-list +++ b/bin/open311-populate-service-list @@ -4,11 +4,18 @@ use strict; use warnings; use FixMyStreet::App; use Open311::PopulateServiceList; +use Getopt::Long::Descriptive; +my ($opt, $usage) = describe_options( + '%c %o', + ['verbose|v', "print out all services as they are found"], + ['help', "print usage message and exit" ], +); +print($usage->text), exit if $opt->help; my $council_list = FixMyStreet::App->model('DB::Open311conf')->search( { send_method => 'Open311' } ); -my $p = Open311::PopulateServiceList->new( council_list => $council_list ); +my $p = Open311::PopulateServiceList->new( council_list => $council_list, verbose => $opt->verbose? 1:0 ); $p->process_councils; diff --git a/bin/pre-install-as-root b/bin/pre-install-as-root new file mode 100755 index 000000000..8d4c9dd26 --- /dev/null +++ b/bin/pre-install-as-root @@ -0,0 +1,307 @@ +#!/bin/sh + +# On a clean Debian squeeze or Ubuntu precise installation you should +# be able to install FixMyStreet with: +# +# curl https://raw.github.com/mysociety/fixmystreet/master/bin/pre-install-as-root | \ +# sh -s fms whatever.compute.amazonaws.com +# +# ... where the first argument is the Unix user who will own the code +# and the application will run as, and the second argument is the +# public hostname for the server, which will be used for creating the +# named virtualhost. + +set -e +set -x + +SITE=fixmystreet + +DEFAULT_SERVER=false +if [ x"$1" = x"--default" ] +then + DEFAULT_SERVER=true + shift +fi + +# Install some packages that we will definitely need: +apt-get install -y git-core lockfile-progs rubygems curl dnsutils lsb-release + +# If we're not running on an EC2 instance, an empty body is returned +# by this request: +EC2_HOSTNAME=`curl -s http://169.254.169.254/latest/meta-data/public-hostname || true` + +usage_and_exit() { + cat >&2 <<EOUSAGE +Usage: $0 [--default] <UNIX-USER> [HOST] +HOST is only optional if you are running this on an EC2 instance. +--default means to install as the default site for this server, +rather than a virtualhost for HOST. +EOUSAGE + exit 1 +} + +if [ $# = 1 ] +then + if [ x = x$EC2_HOSTNAME ] + then + usage_and_exit + else + HOST="$EC2_HOSTNAME" + fi +elif [ $# = 2 ] +then + HOST="$2" +else + usage_and_exit +fi + +UNIX_USER="$1" + +if [ $DEFAULT_SERVER = true ] +then + DIRECTORY="/var/www/$SITE" +else + DIRECTORY="/var/www/$HOST" +fi +REPOSITORY="$DIRECTORY/$SITE" + +REPOSITORY_URL=git://github.com/mysociety/$SITE.git +BRANCH=master + +DISTRIBUTION="$(lsb_release -i -s | tr A-Z a-z)" +VERSION="$(lsb_release -c -s)" + +IP_ADDRESS_FOR_HOST="$(dig +short $HOST)" + +if [ x = x"$IP_ADDRESS_FOR_HOST" ] +then + echo "The hostname $HOST didn't resolve to an IP address" + exit 1 +fi + +generate_locales() { + # If language-pack-en is present, install that: + apt-get install -y language-pack-en || true + + # We get lots of locale errors if the en_GB.UTF-8 locale isn't + # present. (This is from Kagee's script.) + if [ "$(locale -a | egrep -i '^en_GB.utf-?8$' | wc -l)" = "1" ] + then + echo "en_GB.utf8 activated and generated" + else + echo "en_GB.utf8 not generated" + if [ x"$(grep -c '^en_GB.UTF-8 UTF-8' /etc/locale.gen)" = x1 ] + then + echo "'en_GB.UTF-8 UTF-8' already in /etc/locale.gen we will only generate" + else + echo "Appending 'en_GB.UTF-8 UTF-8' and 'cy_GB.UTF-8 UTF-8'" + echo "to /etc/locale.gen for generation" + echo "\nen_GB.UTF-8 UTF-8\ncy_GB.UTF-8 UTF-8" >> /etc/locale.gen + fi + echo "Generating new locales" + locale-gen + fi +} + +set_locale() { + echo 'LANG="en_GB.UTF-8"' > /etc/default/locale + export LANG="en_GB.UTF-8" +} + +add_unix_user() { + # Create the required user if it doesn't already exist: + if id "$1" 2> /dev/null > /dev/null + then + echo "The user $1 already exists." + else + adduser --disabled-password --gecos 'The FixMyStreet User' "$1" + fi +} + +add_postgresql_user() { + su -l -c "createuser --createdb --no-createrole --no-superuser '$UNIX_USER'" postgres || true +} + +update_apt_sources() { + if [ x"$DISTRIBUTION" = x"ubuntu" ] && [ x"$VERSION" = x"precise" ] + then + cat > /etc/apt/sources.list.d/mysociety-extra.list <<EOF +deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise multiverse +deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise multiverse +deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise-updates multiverse +deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise-updates multiverse +EOF + elif [ x"$DISTRIBUTION" = x"debian" ] && [ x"$VERSION" = x"squeeze" ] + then + # Install the basic packages we require: + cat > /etc/apt/sources.list.d/mysociety-extra.list <<EOF +# Debian mirror to use, including contrib and non-free: +deb http://the.earth.li/debian/ squeeze main contrib non-free +deb-src http://the.earth.li/debian/ squeeze main contrib non-free + +# Security Updates: +deb http://security.debian.org/ squeeze/updates main non-free +deb-src http://security.debian.org/ squeeze/updates main non-free + +# Debian Backports +deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free +deb-src http://backports.debian.org/debian-backports squeeze-backports main contrib non-free +EOF + else + echo Unsupport distribution and version combination $DISTRIBUTION $VERSION + exit 1 + fi + apt-get update +} + +clone_or_update_repository() { + # Clone the repository into place if the directory isn't already + # present: + if [ -d $REPOSITORY ] + then + echo the directory $REPOSITORY already exists + cd $REPOSITORY + git remote set-url origin "$REPOSITORY_URL" + git fetch origin + # Check that there are no uncommitted changes before doing a + # git reset --hard: + git diff --quiet || { echo "There were changes in the working tree in $REPOSITORY; exiting."; exit 1; } + git diff --cached --quiet || { echo "There were staged but uncommitted changes in $REPOSITORY; exiting."; exit 1; } + # If that was fine, carry on: + git reset --hard origin/"$BRANCH" + git submodule sync + git submodule update --recursive + else + PARENT="$(dirname $REPOSITORY)" + echo creating $PARENT + mkdir -p $PARENT + git clone --recursive --branch "$BRANCH" "$REPOSITORY_URL" "$REPOSITORY" + fi +} + +install_nginx() { + apt-get install -y nginx libfcgi-procmanager-perl +} + +add_website_to_nginx() { + UNIX_USER="$1" + HOST="$2" + REPOSITORY="$3" + NGINX_SITE="$HOST" + if [ $DEFAULT_SERVER = true ] + then + NGINX_SITE=default + fi + SITE_FILENAME=/etc/nginx/sites-available/"$NGINX_SITE" + SITE_LINK=/etc/nginx/sites-enabled/"$NGINX_SITE" + cp $REPOSITORY/conf/nginx.conf.example $SITE_FILENAME + sed -i "s,/var/www/$SITE,$DIRECTORY," $SITE_FILENAME + if [ $DEFAULT_SERVER = false ] + then + sed -i "/listen 80/a\ +\ server_name $HOST; +" $SITE_FILENAME + fi + ln -nsf "$SITE_FILENAME" "$SITE_LINK" + LOG_DIRECTORY="$(readlink -f $REPOSITORY/../logs)" + mkdir -p "$LOG_DIRECTORY" + chown -R "$UNIX_USER"."$UNIX_USER" "$LOG_DIRECTORY" + /etc/init.d/nginx restart +} + +install_sysvinit_script() { + SYSVINIT_FILENAME=/etc/init.d/$SITE + cp $REPOSITORY/conf/sysvinit.example $SYSVINIT_FILENAME + sed -i "s,/var/www/$SITE,$DIRECTORY,g" $SYSVINIT_FILENAME + sed -i "s/^ *USER=.*/USER=$UNIX_USER/" $SYSVINIT_FILENAME + chmod a+rx $SYSVINIT_FILENAME + update-rc.d $SITE start 20 2 3 4 5 . stop 20 0 1 6 . + /etc/init.d/$SITE restart +} + +install_website_packages() { + EXACT_PACKAGES="$1/conf/packages.$DISTRIBUTION-$VERSION" + PRECISE_PACKAGES="$1/conf/packages.ubuntu-precise" + SQUEEZE_PACKAGES="$1/conf/packages.debian-squeeze" + GENERIC_PACKAGES="$1/conf/packages" + # If there's an exact match for the distribution and release, use that: + if [ -e "$EXACT_PACKAGES" ] + then + PACKAGES_FILE="$EXACT_PACKAGES" + # Otherwise, if this is Ubuntu, and there's a version specifically + # for precise, use that: + elif [ x"$DISTRIBUTION" = x"ubuntu" ] && [ -e "$PRECISE_PACKAGES" ] + then + PACKAGES_FILE="$PRECISE_PACKAGES" + # Otherwise, if this is Debian, and there's a version specifically + # for squeeze, use that: + elif [ x"$DISTRIBUTION" = x"debian" ] && [ -e "$SQUEEZE_PACKAGES" ] + then + PACKAGES_FILE="$SQUEEZE_PACKAGES" + else + PACKAGES_FILE="$GENERIC_PACKAGES" + fi + xargs -a "$PACKAGES_FILE" apt-get -y install +} + +overwrite_rc_local() { + cat > /etc/rc.local <<EOF +#!/bin/sh -e + +su -l -c $REPOSITORY/bin/ec2-rewrite-conf $UNIX_USER +/etc/init.d/$SITE restart + +exit 0 + +EOF + chmod a+rx /etc/rc.local +} + +generate_locales +set_locale + +add_unix_user "$UNIX_USER" + +update_apt_sources + +# And remove one crippling package, if it's installed: +apt-get remove -y --purge apt-xapian-index || true + +clone_or_update_repository $REPOSITORY + +chown -R "$UNIX_USER"."$UNIX_USER" "$DIRECTORY" + +install_nginx + +install_website_packages "$REPOSITORY" + +su -l -c "touch '$DIRECTORY/admin-htpasswd'" "$UNIX_USER" + +add_website_to_nginx "$UNIX_USER" "$HOST" "$REPOSITORY" + +add_postgresql_user "$UNIX_USER" + +DEFAULT_PARAMETER='' +if [ $DEFAULT_SERVER = true ] +then + DEFAULT_PARAMETER='--default' +fi + +su -l -c "$REPOSITORY/bin/install-as-user $DEFAULT_PARAMETER '$UNIX_USER' '$HOST'" "$UNIX_USER" + +install_sysvinit_script + +if [ $DEFAULT_SERVER = true ] && [ x != x$EC2_HOSTNAME ] +then + # If we're setting up as the default on an EC2 instance, + # make sure the ec2-rewrite-conf script is called from + # /etc/rc.local + overwrite_rc_local +fi + +# Tell the user what to do next: + +echo Installation complete - you should now be able to view the site at: +echo http://$HOST/ +echo Or you can run the tests by switching to the "'$UNIX_USER'" user and +echo running: $REPOSITORY/bin/cron-wrapper prove -r t diff --git a/bin/problem-creation-graph b/bin/problem-creation-graph index 6692ae724..b96d45540 100755 --- a/bin/problem-creation-graph +++ b/bin/problem-creation-graph @@ -26,12 +26,12 @@ else DATE="2007-02-01" fi -SOURCEA=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCEB=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCEC=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCED=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCEE=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -GPSCRIPT=/tmp/bci-creation-rate-graph-script-$RANDOM$RANDOM +SOURCEA=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCEB=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCEC=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCED=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCEE=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +GPSCRIPT=/tmp/fms-creation-rate-graph-script-$RANDOM$RANDOM # where status in ('draft') @@ -104,6 +104,6 @@ END #echo "gpscript $GPSCRIPT" export GDFONTPATH=/usr/share/fonts/truetype/ttf-bitstream-vera -gnuplot < $GPSCRIPT > fixmystreet/web/bci-live-creation$EXTENSION 2>/dev/null +gnuplot < $GPSCRIPT > fixmystreet/web/fms-live-creation$EXTENSION 2>/dev/null diff --git a/bin/problems-filed-graph b/bin/problems-filed-graph index 8addacd62..e5946b078 100755 --- a/bin/problems-filed-graph +++ b/bin/problems-filed-graph @@ -20,8 +20,8 @@ source fixmystreet/commonlib/shlib/deployfns read_conf fixmystreet/conf/general.yml -SOURCEO=/tmp/bci-report-rate-graph-data-nonwmc-$RANDOM$RANDOM -GPSCRIPT=/tmp/bci-report-rate-graph-script-$RANDOM$RANDOM +SOURCEO=/tmp/fms-report-rate-graph-data-nonwmc-$RANDOM$RANDOM +GPSCRIPT=/tmp/fms-report-rate-graph-script-$RANDOM$RANDOM echo "select date(created), count(*) @@ -57,5 +57,5 @@ END #echo "gpscript $GPSCRIPT" export GDFONTPATH=/usr/share/fonts/truetype/ttf-bitstream-vera -gnuplot < $GPSCRIPT > fixmystreet/web/bci-live-line$EXTENSION 2>/dev/null +gnuplot < $GPSCRIPT > fixmystreet/web/fms-live-line$EXTENSION 2>/dev/null diff --git a/commonlib b/commonlib -Subproject f81ec03692fac90792fc102f88f0afbf3d2f73b +Subproject cfa9543e2fd50b08d27f6543ae5ef64600bff90 diff --git a/conf/apache-vhost.conf.example b/conf/apache-vhost.conf.example new file mode 100644 index 000000000..97a34fe66 --- /dev/null +++ b/conf/apache-vhost.conf.example @@ -0,0 +1,34 @@ +# An example Apache virtualhost configuration file. +# +# See our installation help at http://code.fixmystreet.com/ + +<VirtualHost *:80> + ServerName fixmystreet.yourservername + DocumentRoot /home/yourname/fixmystreet/web/ + + # Pull in the specific config + Include /home/yourname/fixmystreet/conf/httpd.conf + + <Directory /home/yourname/fixmystreet/web> + # You also need to enable cgi files to run as CGI scripts. For example: + # on production servers these are run under fastcgi + Options +ExecCGI + AddHandler cgi-script .cgi + AllowOverride None + </Directory> + + <Location /admin> + # + # WARNING - enable auth here on production machine + # + </Location> + + Alias /admin/ /home/yourname/fixmystreet/web-admin/ + + Alias /jslib/ /home/yourname/fixmystreet/commonlib/jslib/ + <Location /jslib> + AddOutputFilter DEFLATE js + Header append Cache-Control "no-transform" + </Location> + +</VirtualHost> diff --git a/conf/crontab.example b/conf/crontab.example new file mode 100644 index 000000000..f33e949e8 --- /dev/null +++ b/conf/crontab.example @@ -0,0 +1,28 @@ +# Timed tasks for FixMyStreet. + +# This is an example crontab that you may want to use as a basis for +# one on your own server. You should replace $FMS with the path to the +# clone of the FixMyStreet repository that you are using. You should +# also replace $LOCK_DIR with a writeable directory for the lock files. + +# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. +# Email: matthew@mysociety.org. WWW: http://www.mysociety.org/ + +PATH=/usr/local/bin:/usr/bin:/bin + +5,10,15,20,25,30,35,40,45,50,55 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$FMS/send-reports.lock" "$FMS/bin/cron-wrapper send-reports" || echo "stalled?" +0 0-8,10,11,13,14,16,17,19-23 * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-reports.lock" "$FMS/bin/cron-wrapper send-reports" || echo "stalled?" +0 9,12,15,18 * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-reports.lock" "$FMS/bin/cron-wrapper send-reports --verbose" || echo "stalled?" +2 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-alerts.lock" "$FMS/bin/cron-wrapper send-alerts" || echo "stalled?" +0,30 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-questionnaires.lock" "$FMS/bin/cron-wrapper send-questionnaires" || echo "stalled?" +5,10,15,20,25,30,35,40,45,50,55 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-comments.lock" "$FMS/bin/cron-wrapper send-comments" || echo "stalled?" +5,10,15,20,25,30,35,40,45,50,55 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/fetch-comments.lock" "$FMS/bin/cron-wrapper fetch-comments" || echo "stalled?" +0,30 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/open311-populate-service-list.lock" "$FMS/bin/cron-wrapper open311-populate-service-list" || echo "stalled?" + +# Once an hour, update the all reports stats +13 * * * * "$FMS/bin/cron-wrapper" update-all-reports + +# Once a day on all servers +39 2 * * * "$FMS/bin/problems-filed-graph" +43 2 * * * "$FMS/bin/problem-creation-graph" +00 8 * * * "$FMS/bin/check-for-zombies" $UNIX_USER diff --git a/conf/httpd.conf-example b/conf/httpd.conf-example index e7900161e..ab17dcec3 100644 --- a/conf/httpd.conf-example +++ b/conf/httpd.conf-example @@ -1,42 +1,10 @@ # Apache configuration for FixMyStreet. # -# Add lines something like this to your /etc/apache2/sites-enabled/fixmystreet - -# replacing '/home/yourname/fixmystreet' with the path to your install +# This file should be included in an Apache <VirtualHost> section. An +# example of such a virtualhost configuration file can be found in the +# file apache-vhost.conf.example in this directory. # -# # FixMyStreet -# <VirtualHost *:80> -# ServerName fixmystreet.yourservername -# DocumentRoot /home/yourname/fixmystreet/web/ -# -# # Pull in the specific config -# Include /home/yourname/fixmystreet/conf/httpd.conf -# -# <Directory /home/yourname/fixmystreet/web> -# # You also need to enable cgi files to run as CGI scripts. For example: -# # on production servers these are run under fastcgi -# Options +ExecCGI -# AddHandler cgi-script .cgi -# AllowOverride None -# </Directory> -# -# <Location /admin> -# # -# # WARNING - enable auth here on production machine -# # -# Options +ExecCGI -# AddHandler cgi-script .cgi -# </Location> -# -# Alias /admin/ /home/yourname/fixmystreet/web-admin/ -# -# Alias /jslib/ "/home/yourname/fixmystreet/commonlib/jslib/" -# -# </VirtualHost> -# -# -# Copyright (c) 2011 UK Citizens Online Democracy. All rights reserved. -# Email: team@mysociety.org -# WWW: http://www.mysociety.org +# See our installation help at http://code.fixmystreet.com/ RewriteEngine on # RewriteLog /var/log/apache2/rewrite.log diff --git a/conf/nginx.conf.example b/conf/nginx.conf.example new file mode 100644 index 000000000..7b26afdbf --- /dev/null +++ b/conf/nginx.conf.example @@ -0,0 +1,75 @@ +# An example configuration for running FixMyStreet under nginx. You +# will also need to set up the FixMyStreet Catalyst FastCGI backend. +# An example sysvinit script to help with this is shown given in the file +# sysvinit-catalyst-fastcgi.example in this directory. +# +# See our installation help at http://code.fixmystreet.com/ + +server { + + access_log /var/www/fixmystreet/logs/access.log; + error_log /var/www/fixmystreet/logs/error.log; + + listen 80; + root /var/www/fixmystreet/fixmystreet/web; + error_page 503 /down.html; + + # Make sure that Javascript and CSS are compressed. (HTML is + # already compressed under the default configuration of the nginx + # package.) + + gzip on; + gzip_disable "msie6"; + gzip_types application/javascript application/x-javascript text/css; + + # Set a long expiry time for CSS and Javascript, and prevent + # the mangling of Javascript by proxies: + + location ~ \.css$ { + expires 10y; + } + + location ~ \.js$ { + add_header Cache-Control no-transform; + expires 10y; + try_files $uri @catalyst; + } + + # These rewrite rules are ported from the Apache configuration in + # conf/httpd.conf + + rewrite ^/rss/council/([0-9]+)$ /rss/reports/$1 permanent; + rewrite ^/report$ /reports permanent; + rewrite '^/{/rss/(.*)}$' /rss/$1 permanent; + rewrite '^/reports/{/rss/(.*)}$' /rss/$1 permanent; + rewrite ^/alerts/?$ /alert permanent; + + location /mapit { + proxy_pass http://mapit.mysociety.org/; + proxy_set_header X-Real-IP $remote_addr; + } + + location /admin { + auth_basic "FixMyStreet admin interface"; + auth_basic_user_file /var/www/fixmystreet/admin-htpasswd; + try_files $uri @catalyst; + } + + location / { + if (-f $document_root/down.html) { + return 503; + } + try_files $uri @catalyst; + } + + location /down.html { + internal; + } + + location @catalyst { + include /etc/nginx/fastcgi_params; + fastcgi_param PATH_INFO $fastcgi_script_name; + fastcgi_param SCRIPT_NAME ''; + fastcgi_pass 127.0.0.1:9000; + } +} diff --git a/conf/packages.ubuntu-precise b/conf/packages.ubuntu-precise new file mode 100644 index 000000000..fc8a7d511 --- /dev/null +++ b/conf/packages.ubuntu-precise @@ -0,0 +1,16 @@ +make +jhead +liberror-perl +liblocale-gettext-perl +libsoap-lite-perl +memcached +perl +perlmagick +libmath-bigint-gmp-perl +gettext +libhaml-ruby +postgresql-9.1 +postgresql-server-dev-9.1 +gnuplot +ttf-bitstream-vera +libexpat1-dev diff --git a/conf/sysvinit.example b/conf/sysvinit.example new file mode 100755 index 000000000..44424281b --- /dev/null +++ b/conf/sysvinit.example @@ -0,0 +1,53 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: application-catalyst-fixmystreet +# Required-Start: $local_fs $network +# Required-Stop: $local_fs $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Starts the FastCGI app server for the "FixMyStreet" site +# Description: The FastCGI application server for the "FixMyStreet" site +### END INIT INFO + +# This example sysvinit script is based on the helpful example here: +# http://richard.wallman.org.uk/2010/02/howto-deploy-a-catalyst-application-using-fastcgi-and-nginx/ + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +SITE_HOME=/var/www/fixmystreet +NAME=fixmystreet +DESC="FixMyStreet app server" +USER=fms + +echo $DAEMON +test -f $DAEMON || exit 0 + +set -e + +start_daemon() { + su -l -c "cd $SITE_HOME/fixmystreet && bin/cron-wrapper web/fixmystreet_app_fastcgi.cgi -d -l :9000 -n 2" $USER +} + +stop_daemon() { + pkill -f perl-fcgi -u $USER || true +} + +case "$1" in + start) + start_daemon + ;; + stop) + stop_daemon + ;; + reload|restart|force-reload) + stop_daemon + sleep 5 + start_daemon + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|reload|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/db/alert_types.sql b/db/alert_types.sql index 4ebd33cf9..4116d29dc 100644 --- a/db/alert_types.sql +++ b/db/alert_types.sql @@ -17,7 +17,7 @@ insert into alert_type item_title, item_link, item_description, template) values ('new_problems', '', '', 'New problems on FixMyStreet', '/', 'The latest problems reported by users', - 'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', + 'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem'); -- New fixed problems anywhere on the site @@ -28,7 +28,7 @@ insert into alert_type item_title, item_link, item_description, template) values ('new_fixed_problems', '', '', 'Problems recently reported fixed on FixMyStreet', '/', 'The latest problems reported fixed by users', - 'problem', 'problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')', 'lastupdate desc', + 'problem', 'problem.non_public = ''f'' and problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')', 'lastupdate desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem'); -- New problems around a location @@ -39,7 +39,7 @@ insert into alert_type item_title, item_link, item_description, template) values ('local_problems', '', '', 'New local problems on FixMyStreet', '/', 'The latest local problems reported by users', - 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', + 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby'); -- New problems around a location @@ -50,7 +50,7 @@ insert into alert_type item_title, item_link, item_description, template) values ('local_problems_state', '', '', 'New local problems on FixMyStreet', '/', 'The latest local problems reported by users', - 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (?)', 'created desc', + 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (?)', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby'); -- New problems around a postcode @@ -61,7 +61,7 @@ insert into alert_type item_title, item_link, item_description, template) values ('postcode_local_problems', '', '', 'New problems near {{POSTCODE}} on FixMyStreet', '/', 'The latest local problems reported by users', - 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', + 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby'); -- New problems around a postcode with a particular state @@ -72,7 +72,7 @@ insert into alert_type item_title, item_link, item_description, template) values ('postcode_local_problems_state', '', '', 'New problems near {{POSTCODE}} on FixMyStreet', '/', 'The latest local problems reported by users', - 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (?)', 'created desc', + 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (?)', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby'); -- New problems sent to a particular council @@ -83,7 +83,7 @@ insert into alert_type item_title, item_link, item_description, template) values ('council_problems', '', '', 'New problems to {{COUNCIL}} on FixMyStreet', '/reports', 'The latest problems for {{COUNCIL}} reported by users', - 'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%'' + 'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%'' or council is null) and areas like ''%,''||?||'',%''', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-council' ); @@ -97,7 +97,7 @@ insert into alert_type values ('ward_problems', '', '', 'New problems for {{COUNCIL}} within {{WARD}} ward on FixMyStreet', '/reports', 'The latest problems for {{COUNCIL}} within {{WARD}} ward reported by users', - 'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%'' + 'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%'' or council is null) and areas like ''%,''||?||'',%''', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-ward' ); @@ -111,7 +111,7 @@ insert into alert_type values ('area_problems', '', '', 'New problems within {{NAME}}''s boundary on FixMyStreet', '/reports', 'The latest problems within {{NAME}}''s boundary reported by users', 'problem', - 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and areas like ''%,''||?||'',%''', 'created desc', + 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and areas like ''%,''||?||'',%''', 'created desc', '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-area' ); diff --git a/db/generate_secret.sql b/db/generate_secret.sql new file mode 100644 index 000000000..ad4b48200 --- /dev/null +++ b/db/generate_secret.sql @@ -0,0 +1,8 @@ +-- assumes there's a secret table (from the schema.sql) +-- use your own secret if you have one :-) +-- otherwise you can use this to populate the secret table with a random secret + +-- empty the table in case it has a value already (i.e., this is *destructive*!) +delete from secret; + +insert into secret values (md5(random()::text)); diff --git a/db/migrate_from_osgb36_to_wgs84.pl b/db/migrate_from_osgb36_to_wgs84.pl index abd504fb8..676ffea9b 100644 --- a/db/migrate_from_osgb36_to_wgs84.pl +++ b/db/migrate_from_osgb36_to_wgs84.pl @@ -21,11 +21,11 @@ use Utils; BEGIN { mySociety::Config::set_file("$FindBin::Bin/../conf/general"); mySociety::DBHandle::configure( - Name => mySociety::Config::get('BCI_DB_NAME'), - User => mySociety::Config::get('BCI_DB_USER'), - Password => mySociety::Config::get('BCI_DB_PASS'), - Host => mySociety::Config::get( 'BCI_DB_HOST', undef ), - Port => mySociety::Config::get( 'BCI_DB_PORT', undef ) + Name => mySociety::Config::get('FMS_DB_NAME'), + User => mySociety::Config::get('FMS_DB_USER'), + Password => mySociety::Config::get('FMS_DB_PASS'), + Host => mySociety::Config::get( 'FMS_DB_HOST', undef ), + Port => mySociety::Config::get( 'FMS_DB_PORT', undef ) ); } diff --git a/db/schema.sql b/db/schema.sql index a4323f880..1f0d0d4c3 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -83,6 +83,9 @@ create table contacts ( -- extra fields required for open311 extra text, + -- for things like missed bin collections + non_public boolean default 'f' + -- per contact endpoint configuration endpoint text, jurisdiction text default '', @@ -206,6 +209,9 @@ create table problem ( -- record send_method used, which can be used to infer usefulness of external_id send_method_used text, + -- for things like missed bin collections + non_public BOOLEAN default 'f' + -- record details about messages from external sources, eg. message manager external_source text, external_source_id text, diff --git a/db/schema_0024-add_non_public_categories_and_problems.sql b/db/schema_0024-add_non_public_categories_and_problems.sql new file mode 100644 index 000000000..c133b3ef2 --- /dev/null +++ b/db/schema_0024-add_non_public_categories_and_problems.sql @@ -0,0 +1,37 @@ +BEGIN; + + ALTER TABLE contacts + ADD COLUMN non_public BOOLEAN DEFAULT 'f'; + + ALTER TABLE problem + ADD COLUMN non_public BOOLEAN DEFAULT 'f'; + + + UPDATE alert_type set item_where = 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in + (''confirmed'', ''investigating'', ''planned'', ''in progress'', + ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')' WHERE ref = 'postcode_local_problems'; + UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in + (''confirmed'', ''investigating'', ''planned'', ''in progress'', + ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'' )' WHERE ref = 'new_problems'; + UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')' WHERE ref = 'new_fixed_problems'; + UPDATE alert_type set item_where = 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in + (''confirmed'', ''investigating'', ''planned'', ''in progress'', + ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')' WHERE ref = 'local_problems'; + UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in + (''confirmed'', ''investigating'', ''planned'', ''in progress'', + ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and + (council like ''%''||?||''%'' or council is null) and + areas like ''%,''||?||'',%''' WHERE ref = 'council_problems'; + UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in + (''confirmed'', ''investigating'', ''planned'', ''in progress'', + ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and + (council like ''%''||?||''%'' or council is null) and + areas like ''%,''||?||'',%''' WHERE ref = 'ward_problems'; + UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in + (''confirmed'', ''investigating'', ''planned'', ''in progress'', + ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and + areas like ''%,''||?||'',%''' WHERE ref = 'area_problems'; + +commit; + +COMMIT; diff --git a/locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.mo b/locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.mo Binary files differdeleted file mode 100644 index e09194c2b..000000000 --- a/locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.mo +++ /dev/null diff --git a/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po b/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po index 58b307d58..bcf77f56c 100644 --- a/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po +++ b/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po @@ -5,20 +5,22 @@ # # Matthew Somerville <matthew@mysociety.org>, 2008-04-15. # Petter Reinholdtsen <pere@hungry.com>, 2011. +# Anders Einar Hilden <hildenae@gmail.com>, 2012. msgid "" msgstr "" "Project-Id-Version: FixMyStreet\n" "Report-Msgid-Bugs-To: matthew@mysociety.org\n" "POT-Creation-Date: 2012-08-21 09:54+0100\n" -"PO-Revision-Date: 2012-08-07 01:09+0100\n" +"PO-Revision-Date: 2012-09-14 00:22+0100\n" "Last-Translator: Anders Einar Hilden <hildenae@gmail.com>\n" "Language-Team: Norwegian Bokmål <i18n-nb@lister.ping.uio.no>\n" -"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: KBabel 1.11.4\n" +"X-Poedit-Basepath: ../../../\n" +"Language: Norwegian Bokmål\n" #: perllib/FixMyStreet/DB/Result/Problem.pm:555 #: perllib/FixMyStreet/DB/ResultSet/Problem.pm:337 @@ -107,7 +109,7 @@ msgstr "%s - oppsummeringsrapporter" #: perllib/FixMyStreet/DB/Result/Problem.pm:605 msgid "%s ref: %s" -msgstr "" +msgstr "%s ref: %s" #: perllib/FixMyStreet/Cobrand/UK.pm:288 perllib/FixMyStreet/Cobrand/UK.pm:300 msgid "%s ward, %s" @@ -150,9 +152,8 @@ msgstr "(alternativt kan RSS-strømmen tilpasses, innenfor" #: templates/web/default/around/around_map_list_items.html:12 #: templates/web/default/around/on_map_list_items.html:9 #: templates/web/fixmystreet/report/_item.html:23 -#, fuzzy msgid "(closed)" -msgstr "Lukket" +msgstr "(lukket)" #: templates/web/default/around/around_map_list_items.html:10 #: templates/web/default/around/on_map_list_items.html:7 @@ -203,12 +204,11 @@ msgstr "-- Velg en kategori --" msgid "-- Pick a property type --" msgstr "-- Velg en eiendomsstype --" -# Bør "portalen" byttes ut med et annet ord? (trenger kontekst) +# Trenger kontekst for bedre oversettelse #: templates/web/default/tokens/confirm_problem.html:14 #: templates/web/default/tokens/confirm_problem.html:22 -#, fuzzy msgid ". You can <a href=\"%s%s\">view the problem on this site</a>." -msgstr ". Du kan <a href=\"%s\">lese om problemet på portalen </a>." +msgstr ". Du kan <a href=\"%s\">lese om problemet på denne siden</a>." #: templates/web/default/questionnaire/completed.html:20 msgid "" @@ -218,8 +218,8 @@ msgstr "" "<p style=\"font-size:150%\">Tusen takk for at du fylte ut vårt spørreskjema. " "Vi er glad for å høre at ditt problem er blitt fikset.</p>" +# Er pledgebank noe vi vil sende uvitende, norske innbyggere til? #: templates/web/fiksgatami/questionnaire/completed-open.html:1 -#, fuzzy msgid "" "<p style=\"font-size:150%\">We’re sorry to hear that. We have two\n" "suggestions: why not try <a href=\"http://www.norge.no/styresmakter/" @@ -229,15 +229,14 @@ msgid "" "<a href=\"http://www.pledgebank.com/new\">make and publicise a pledge</a>?\n" "</p>" msgstr "" -"<p style=\"font-size:150%%\">Det var trist å høre dette. Vi har to forslag: " +"<p style=\"font-size:150%\">Det var trist å høre dette. Vi har to forslag: " "hva med å forsøke\n" -"<a href=\"%s\">å skrive direkte til dine representanter</a>, eller hvis det " -"er et problem som kan fikses\n" +"<a href=\"http://www.norge.no/styresmakter/\">å skrive direkte til dine \n" +"representanter</a>, eller hvis det er et problem som kan fikses\n" "av folk i nabolaget som jobber sammen, hva med å <a href=\"http://www." "pledgebank.com/new\">publisere en utfordring om å bidra</a>?</p>" #: templates/web/fixmystreet/questionnaire/completed-open.html:1 -#, fuzzy msgid "" "<p style=\"font-size:150%\">We’re sorry to hear that. We have two\n" "suggestions: why not try <a href=\"http://www.writetothem.com/\">writing " @@ -248,7 +247,7 @@ msgid "" "<a href=\"http://www.pledgebank.com/new\">make and publicise a pledge</a>?\n" "</p>" msgstr "" -"<p style=\"font-size:150%%\">Det var trist å høre dette. Vi har to forslag: " +"<p style=\"font-size:150%\">Det var trist å høre dette. Vi har to forslag: " "hva med å forsøke\n" "<a href=\"%s\">å skrive direkte til dine representanter</a>, eller hvis det " "er et problem som kan fikses\n" @@ -256,7 +255,6 @@ msgstr "" "pledgebank.com/new\">publisere en utfordring om å bidra</a>?</p>" #: templates/web/default/questionnaire/completed-open.html:1 -#, fuzzy msgid "" "<p style=\"font-size:150%\">We’re sorry to hear that. We have two\n" "suggestions: why not try writing to your local representative or, if " @@ -267,8 +265,8 @@ msgid "" msgstr "" "<p style=\"font-size:150%%\">Det var trist å høre dette. Vi har to forslag: " "hva med å forsøke\n" -"<a href=\"%s\">å skrive direkte til dine representanter</a>, eller hvis det " -"er et problem som kan fikses\n" +"å skrive direkte til dine representanter, eller hvis det er et problem som " +"kan fikses\n" "av folk i nabolaget som jobber sammen, hva med å <a href=\"http://www." "pledgebank.com/new\">publisere en utfordring om å bidra</a>?</p>" @@ -429,12 +427,11 @@ msgstr "All informasjonen du har lagt inn her vil bli sendt til" #: templates/web/default/report/new/councils_text_all.html:10 #: templates/web/default/report/new/councils_text_all.html:12 -#, fuzzy msgid "" "All the information you provide here will be sent to <strong>%s</strong> or " "<strong>Roads Service</strong>." msgstr "" -"All informasjonen du har lagt inn her vil bli sendt til <strong>%s</strong>." +"All informasjon du legger inn her vil bli sendt til <strong>%s</strong>." #: templates/web/default/report/new/councils_text_all.html:3 #: templates/web/default/report/new/councils_text_all.html:5 @@ -768,7 +765,7 @@ msgstr "For tiden har 1+ slettet" #: templates/web/default/dashboard/index.html:5 #: templates/web/default/dashboard/index.html:7 msgid "Dashboard" -msgstr "" +msgstr "Oversikt" #: templates/web/default/admin/council_contacts.html:38 #: templates/web/default/admin/council_contacts.html:85 @@ -906,22 +903,22 @@ msgstr "Sluttmåned:" msgid "Enter a nearby GB postcode, or street name and area" msgstr "Skriv inn GB-postnummer i nærheten, eller veinavn og sted" +# Fra UK cobrand #: perllib/FixMyStreet/Cobrand/UK.pm:18 -#, fuzzy msgid "Enter a nearby UK postcode, or street name and area" -msgstr "Skriv inn postnummer i nærheten, eller veinavn og sted" +msgstr "Skriv inn et britisk postnummer i nærheten, eller veinavn og sted" #: perllib/FixMyStreet/Cobrand/FiksGataMi.pm:25 msgid "Enter a nearby postcode, or street name and area" msgstr "Skriv inn postnummer i nærheten, eller veinavn og sted" +# Kan "Oppgi" være bedre? #: templates/web/default/around/postcode_form.html:1 #: templates/web/default/around/postcode_form.html:2 #: templates/web/fixmystreet/around/postcode_form.html:10 #: templates/web/fixmystreet/around/postcode_form.html:11 -#, fuzzy msgid "Enter a nearby street name and area" -msgstr "Skriv inn postnummer i nærheten, eller veinavn og sted" +msgstr "Skriv inn et veinavn og sted" #: templates/web/default/auth/general.html:64 #: templates/web/default/report/display.html:171 @@ -962,9 +959,8 @@ msgid "Examples:" msgstr "Eksempler:" #: templates/web/default/admin/report_edit.html:40 -#, fuzzy msgid "Extra data:" -msgstr "Merkevaresamarbeidsdata:" +msgstr "Ekstra data:" #: templates/web/bromley/contact/submit.html:14 #: templates/web/default/contact/submit.html:15 @@ -978,9 +974,8 @@ msgstr "" #: templates/web/bromley/report/display.html:189 #: templates/web/bromley/report/new/fill_in_details_form.html:113 #: templates/web/bromley/report/new/fill_in_details_form.html:160 -#, fuzzy msgid "First Name" -msgstr "Første gang" +msgstr "Fornavn" #: templates/web/default/questionnaire/index.html:79 #: templates/web/fixmystreet/questionnaire/index.html:73 @@ -1117,7 +1112,6 @@ msgstr "Få oppdateringer" #: templates/web/fixmystreet/reports/_rss.html:3 #: templates/web/fixmystreet/reports/_rss.html:9 -#, fuzzy msgid "Get updates of %s problems" msgstr "Få oppdateringer for problemer i denne %s" @@ -1389,9 +1383,8 @@ msgstr "Husk min innlogging på denne datamaskinen" #: templates/web/bromley/report/display.html:195 #: templates/web/bromley/report/new/fill_in_details_form.html:119 #: templates/web/bromley/report/new/fill_in_details_form.html:166 -#, fuzzy msgid "Last Name" -msgstr "Siste oppdatering:" +msgstr "Etternavn" #: templates/web/default/admin/council_contacts.html:39 msgid "Last editor" @@ -1950,6 +1943,8 @@ msgid "" "Please describe the exact location of the report. Example: “2 dumped " "mattresses outside Number 19 Stockwell Close”" msgstr "" +"Vennligst beskriv den nøyaktige posisjonen til problemet. For eksempel: «2 " +"madrasser dumpet utenfor Jernbanegata 19»" #: templates/web/default/contact/blurb.html:2 msgid "" @@ -2022,9 +2017,8 @@ msgid "Please enter your email address" msgstr "Vennligst tast inn din e-postadresse" #: templates/web/default/js/validation_strings.html:19 -#, fuzzy msgid "Please enter your first name" -msgstr "Legg inn ditt navn" +msgstr "Vennligst tast inn ditt fornavn" #: perllib/FixMyStreet/DB/Result/Problem.pm:340 #: templates/web/default/js/validation_strings.html:7 @@ -2045,14 +2039,12 @@ msgid "Please enter your name" msgstr "Legg inn ditt navn" #: templates/web/default/js/validation_strings.html:20 -#, fuzzy msgid "Please enter your second name" -msgstr "Legg inn ditt navn" +msgstr "Vennligst tast inn ditt mellomnavn" #: templates/web/default/js/validation_strings.html:18 -#, fuzzy msgid "Please enter your title" -msgstr "Legg inn din e-post" +msgstr "Vennligst legg inn din tittel" #: templates/web/emptyhomes/report/new/fill_in_details_text.html:1 msgid "" @@ -2112,6 +2104,8 @@ msgstr "Vennligst indiker om du ønsker å motta et nytt spørreskjema" #: templates/web/fixmystreet/report/updates-sidebar-notes.html:3 msgid "Please note that updates are not sent to the council." msgstr "" +"Vær oppmerksom på at oppdaterginger ikke blir videresendt til " +"administrasjonen." #: templates/web/default/report/display.html:56 msgid "" @@ -2125,16 +2119,15 @@ msgstr "" "\">personvernpolicy</a>" #: templates/web/barnet/report/updates-sidebar-notes.html:1 -#, fuzzy msgid "" "Please note that updates are not sent to the relevant department. If you " "leave your name it will be public. Your information will only be used in " "accordance with our <a href=\"/faq#privacy\">privacy policy</a>" msgstr "" -"Vennligst merk at oppdateringer ikke blir sendt til administrasjonen. Hvis " -"du legger igjen navnet ditt så vil det være offentlig tilgjengelig. Din " +"Vennligst merk at oppdateringer ikke vil bli sendt til administrasjonen. " +"Dersom du legger igjen navnet ditt vil det være synlig for alle. Din " "informasjon vil kun bli brukt i henhold til våre <a href=\"/faq#privacy" -"\">personvernpolicy</a>" +"\">personvernsregler</a>" #: templates/web/bromley/report/new/fill_in_details_form.html:23 #: templates/web/default/report/new/fill_in_details_form.html:5 @@ -2190,9 +2183,8 @@ msgid "Please upload a JPEG image only" msgstr "Vennligst last opp kun JPEG-bilder" #: perllib/FixMyStreet/App/Controller/Photo.pm:183 -#, fuzzy msgid "Please upload a JPEG image only\n" -msgstr "Vennligst last opp kun JPEG-bilder" +msgstr "Vennligst last opp kun JPEG eller JPG-bilder\n" #: perllib/FixMyStreet/App/Controller/Contact.pm:98 msgid "Please write a message" @@ -2327,14 +2319,13 @@ msgid "Provide an update" msgstr "Bidra med en oppdatering" #: templates/web/bromley/report/new/fill_in_details_form.html:180 -#, fuzzy msgid "" "Providing a password is optional, but doing so will allow you to more easily " "report future problems, leave updates and manage your reports." msgstr "" "Det er valgfritt å oppgi et passord, men om du gjør det vil det bli enklere " "for deg å rapportere problemer, legge inn oppdateringer og holde oversikt " -"over dine rapporter" +"over dine rapporter." #: templates/web/bromley/report/display.html:142 #: templates/web/default/report/display.html:175 @@ -2947,14 +2938,13 @@ msgstr "" "å løse UKs tomme hjem-krise." #: templates/web/fixmystreet/around/around_index.html:27 -#, fuzzy msgid "" "Thanks for uploading your photo. We now need to locate your problem, so " "please enter a nearby street name or postcode in the box above :" msgstr "" -"Takk for at du lastet opp ditt bilde. Nå trenger vi å plassere ditt problem," -"så vær så snill å skriv inn navn på vei i nærheten, eller postnummer i " -"boksen under :" +"Takk for at du lastet opp ditt bilde. Vi må nå plassere ditt problem, så " +"vær så snill å skriv inn navnet på en vei eller et postnummer i området i " +"boksen ovenfor :" #: templates/web/default/around/around_index.html:28 msgid "" @@ -2983,17 +2973,15 @@ msgid "" msgstr "Bildet ser ikke ut til å blitt lastet opp riktig (%s), prøv på nytt." #: perllib/FixMyStreet/App/Controller/Council.pm:91 -#, fuzzy msgid "" "That location does not appear to be covered by a council; perhaps it is " "offshore or outside the country. Please try again." msgstr "" -"Det stedet dekkes ikke av noen administrasjon, kanskje det er til havs - " -"vennligst forsøk et mer spesifikt sted." +"Det stedet dekkes ikke av noen administrasjon, kanskje det er til havs eller " +"utenfor lander - vennligst forsøk et annet sted." # Should this be "Norge" or "Storbritannia" ? #: perllib/FixMyStreet/App/Controller/Location.pm:107 -#, fuzzy msgid "That location does not appear to be in the UK; please try again." msgstr "Det stedet virker ikke å være i Storbritannia. Vennligst prøv igjen." @@ -3199,11 +3187,8 @@ msgstr "" "senere." #: perllib/FixMyStreet/App/Controller/Dashboard.pm:59 -#, fuzzy msgid "There was a problem showing this page. Please try again later." -msgstr "" -"Det var problemer med å vise 'Alle rapporter'-siden. Vennligst prøv igjen " -"senere." +msgstr "Det var problemer med å vise denne siden. Vennligst prøv igjen senere." #: perllib/FixMyStreet/App/Controller/Report/New.pm:733 #: perllib/FixMyStreet/App/Controller/Report/Update.pm:130 @@ -3370,12 +3355,11 @@ msgstr "" "For å <strong>rapportere et problem</strong>, klikk på kartet på riktig sted." #: templates/web/default/alert/index.html:27 -#, fuzzy msgid "" "To find out what local alerts we have for you, please enter your postcode or " "street name and area" msgstr "" -"Du finner lokale problemer ved å søke på ditt postnummer, veinavn eller sted:" +"Du finner lokale problemer ved å søke på ditt postnummer, veinavn eller sted" #: perllib/FixMyStreet/DB/ResultSet/Problem.pm:268 msgid "To view a map of the precise location of this issue" @@ -3505,9 +3489,8 @@ msgid "View report on site" msgstr "Se rapport på nettstedet" #: templates/web/default/reports/council.html:18 -#, fuzzy msgid "View reports by ward" -msgstr "Se rapport på nettstedet" +msgstr "Se rapport per bydel" #: templates/web/emptyhomes/tokens/confirm_problem.html:39 msgid "View your report" @@ -3595,13 +3578,12 @@ msgstr "" "faq#privacy\">personvernpolicy.</a>" #: templates/web/fixmystreet/report/new/notes.html:4 -#, fuzzy msgid "" "We will only use your personal information in accordance with our <a href=\"/" "privacy\">privacy policy.</a>" msgstr "" -"Vi vil kun bruke personlig informasjon om deg i henhold til vår <a href=\"/" -"faq#privacy\">personvernpolicy.</a>" +"Vi vil kun bruke personlige informasjon om deg i henhold til våre <a href=\"/" +"faq#privacy\">personvernsregler.</a>" #: templates/web/emptyhomes/contact/blurb.html:2 msgid "" @@ -3648,7 +3630,6 @@ msgstr "" "href=\"%s\">MaPit</a>." #: templates/web/fixmystreet/footer.html:22 -#, fuzzy msgid "" "Would you like better integration with FixMyStreet? <a href=\"http://www." "mysociety.org/for-councils/fixmystreet/\">Find out about FixMyStreet for " @@ -3886,25 +3867,22 @@ msgstr "Din e-post" #: templates/web/bromley/report/display.html:193 #: templates/web/bromley/report/new/fill_in_details_form.html:117 #: templates/web/bromley/report/new/fill_in_details_form.html:164 -#, fuzzy msgid "Your first name" -msgstr "Ditt navn" +msgstr "Ditt fornavn" #: templates/web/fixmystreet/report/updates-sidebar-notes.html:5 -#, fuzzy msgid "" "Your information will only be used in accordance with our <a href=\"/privacy" "\">privacy policy</a>" msgstr "" -"Vi vil kun bruke personlig informasjon om deg i henhold til vår <a href=\"/" -"faq#privacy\">personvernpolicy.</a>" +"Vi vil kun bruke personlig informasjon om deg i henhold til våre <a href=\"/" +"faq#privacy\">personvernsregler.</a>" #: templates/web/bromley/report/display.html:199 #: templates/web/bromley/report/new/fill_in_details_form.html:123 #: templates/web/bromley/report/new/fill_in_details_form.html:170 -#, fuzzy msgid "Your last name" -msgstr "Ditt navn" +msgstr "Ditt etternavn" #: templates/web/fixmystreet/auth/general.html:53 #: templates/web/fixmystreet/contact/index.html:65 @@ -4043,7 +4021,7 @@ msgstr "kartet ble ikke brukt, så nåleposisjon kan være unøyaktig" #: perllib/FixMyStreet/DB/Result/Problem.pm:603 msgid "their ref: %s" -msgstr "" +msgstr "deres ref: %s" #: perllib/FixMyStreet/DB/ResultSet/Problem.pm:330 msgid "this type of local problem" diff --git a/notes/no-update-server b/notes/no-update-server index 2d149d850..da3656829 100644 --- a/notes/no-update-server +++ b/notes/no-update-server @@ -511,7 +511,7 @@ case "$1" in ;; update) fetch_git_source - fgmdbpassword=$(grep OPTION_BCI_DB_PASS $basedir/fixmystreet/conf/general | cut -d\' -f4) + fgmdbpassword=$(grep OPTION_FMS_DB_PASS $basedir/fixmystreet/conf/general | cut -d\' -f4) midbpassword=$(grep OPTION_MAPIT_DB_PASS $basedir/mapit/conf/general | cut -d\' -f4) update_fixmystreet_config www-data $fgmdbpassword fixmystreet diff --git a/perllib/CrossSell.pm b/perllib/CrossSell.pm index f9a02a61b..f9cde6936 100644 --- a/perllib/CrossSell.pm +++ b/perllib/CrossSell.pm @@ -19,7 +19,6 @@ package CrossSell; use strict; use LWP::Simple qw($ua get); -$ua->timeout(5); use URI::Escape; use mySociety::AuthToken; use mySociety::Web qw(ent); @@ -169,6 +168,8 @@ sub display_advert ($$;$%) { return '' unless $c->cobrand->moniker eq 'fixmystreet'; + $ua->timeout(5); + #if (defined $data{council} && $data{council} eq '2326') { # my ($out, $ad) = display_hfyc_cheltenham_advert($email, $name); # if ($out) { diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index f05639b41..2d1cf2c5a 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -301,6 +301,7 @@ sub update_contacts : Private { $contact->email( $email ); $contact->confirmed( $c->req->param('confirmed') ? 1 : 0 ); $contact->deleted( $c->req->param('deleted') ? 1 : 0 ); + $contact->non_public( $c->req->param('non_public') ? 1 : 0 ); $contact->note( $c->req->param('note') ); $contact->whenedited( \'ms_current_timestamp()' ); $contact->editor( $editor ); @@ -649,6 +650,7 @@ sub report_edit : Path('report_edit') : Args(1) { } my $flagged = $c->req->param('flagged') ? 1 : 0; + my $non_public = $c->req->param('non_public') ? 1 : 0; # do this here so before we update the values in problem if ( $c->req->param('anonymous') ne $problem->anonymous @@ -656,8 +658,10 @@ sub report_edit : Path('report_edit') : Args(1) { || $c->req->param('email') ne $problem->user->email || $c->req->param('title') ne $problem->title || $c->req->param('detail') ne $problem->detail - || $flagged != $problem->flagged ) + || $flagged != $problem->flagged + || $non_public != $problem->non_public ) { + warn "edited"; $edited = 1; } @@ -667,6 +671,7 @@ sub report_edit : Path('report_edit') : Args(1) { $problem->state( $c->req->param('state') ); $problem->name( $c->req->param('name') ); $problem->flagged( $flagged ); + $problem->non_public( $non_public ); if ( $c->req->param('email') ne $problem->user->email ) { my $user = $c->model('DB::User')->find_or_create( diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 57d27b3e4..a7e1e8a3a 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -91,6 +91,13 @@ sub load_problem_or_display_error : Private { '/page_error_410_gone', [ _('That report has been removed from FixMyStreet.') ] # ); + } elsif ( $problem->non_public ) { + if ( !$c->user || $c->user->id != $problem->user->id ) { + $c->detach( + '/page_error_403_access_denied', + [ _('That report cannot be viewed on FixMyStreet.') ] # + ); + } } $c->stash->{problem} = $problem; diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index b18e6e39f..a4462e035 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -595,6 +595,8 @@ sub setup_categories_and_councils : Private { my @category_options = (); # categories to show my $category_label = undef; # what to call them my %category_extras = (); # extra fields to fill in for open311 + my %non_public_categories = + (); # categories for which the reports are not public # FIXME - implement in cobrand if ( $c->cobrand->moniker eq 'emptyhomes' ) { @@ -646,6 +648,8 @@ sub setup_categories_and_councils : Private { $category_extras{ $contact->category } = $contact->extra if $contact->extra; + + $non_public_categories{ $contact->category } = 1 if $contact->non_public; } $seen{$contact->category} = 1; } @@ -663,6 +667,7 @@ sub setup_categories_and_councils : Private { $c->stash->{category_label} = $category_label; $c->stash->{category_options} = \@category_options; $c->stash->{category_extras} = \%category_extras; + $c->stash->{non_public_categories} = \%non_public_categories; $c->stash->{category_extras_json} = encode_json \%category_extras; $c->stash->{extra_name_info} = $first_council->{id} == COUNCIL_ID_BROMLEY ? 1 : 0; @@ -872,6 +877,10 @@ sub process_report : Private { }; } + if ( $c->stash->{non_public_categories}->{ $report->category } ) { + $report->non_public( 1 ); + } + $c->cobrand->process_extras( $c, $contacts[0]->area_id, \@extra ); if ( @extra ) { diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm index 37766db44..444389ec2 100644 --- a/perllib/FixMyStreet/App/Controller/Reports.pm +++ b/perllib/FixMyStreet/App/Controller/Reports.pm @@ -170,13 +170,6 @@ sub rss_ward : Regex('^rss/(reports|area)$') : Args(2) { $url .= '/' . $c->cobrand->short_name( $c->stash->{ward} ) if $c->stash->{ward}; $c->stash->{qs} = "/$url"; - my @params; - push @params, $c->stash->{council}->{id} if $rss eq 'reports'; - push @params, $c->stash->{ward} - ? $c->stash->{ward}->{id} - : $c->stash->{council}->{id}; - $c->stash->{db_params} = [ @params ]; - if ( $rss eq 'area' && $c->stash->{ward} ) { # All problems within a particular ward $c->stash->{type} = 'area_problems'; @@ -236,6 +229,7 @@ sub council_check : Private { type => $area_types, min_generation => $c->cobrand->area_min_generation ); + if (keys %$areas == 1) { ($c->stash->{council}) = values %$areas; return; @@ -318,7 +312,8 @@ sub load_and_group_problems : Private { my $page = $c->req->params->{p} || 1; my $where = { - state => [ FixMyStreet::DB::Result::Problem->visible_states() ] + non_public => 0, + state => [ FixMyStreet::DB::Result::Problem->visible_states() ] }; if ($c->stash->{ward}) { $where->{areas} = { 'like', '%,' . $c->stash->{ward}->{id} . ',%' }; diff --git a/perllib/FixMyStreet/App/Controller/Root.pm b/perllib/FixMyStreet/App/Controller/Root.pm index 7f7d7f5fd..769a147bf 100644 --- a/perllib/FixMyStreet/App/Controller/Root.pm +++ b/perllib/FixMyStreet/App/Controller/Root.pm @@ -94,6 +94,13 @@ sub page_error_410_gone : Private { $c->response->status(410); } +sub page_error_403_access_denied : Private { + my ( $self, $c, $error_msg ) = @_; + $c->stash->{template} = 'index.html'; + $c->stash->{error} = $error_msg; + $c->response->status(403); +} + =head2 end Attempt to render a view, if needed. diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index 64e08f44c..cfc9455b5 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -4,6 +4,7 @@ use base 'FixMyStreet::Cobrand::Base'; use strict; use warnings; use FixMyStreet; +use Encode; use URI; use Digest::MD5 qw(md5_hex); @@ -674,7 +675,9 @@ sub _fallback_council_sender { }; sub example_places { - return FixMyStreet->config('EXAMPLE_PLACES') || [ 'High Street', 'Main Street' ]; + my $e = FixMyStreet->config('EXAMPLE_PLACES') || [ 'High Street', 'Main Street' ]; + $e = [ map { Encode::decode('UTF-8', $_) } @$e ]; + return $e; } =head2 only_authed_can_create diff --git a/perllib/FixMyStreet/Cobrand/UK.pm b/perllib/FixMyStreet/Cobrand/UK.pm index feb3c9ecf..75f6ba061 100644 --- a/perllib/FixMyStreet/Cobrand/UK.pm +++ b/perllib/FixMyStreet/Cobrand/UK.pm @@ -145,13 +145,13 @@ sub find_closest { my $str = $self->SUPER::find_closest( $latitude, $longitude, $problem ); # Get nearest postcode from Matthew's random gazetteer (put in MaPit? Or elsewhere?) - my $url = "http://gazetteer.dracos.vm.bytemark.co.uk/point/$latitude,$longitude.json"; + my $url = "http://mapit.mysociety.org/nearest/4326/$longitude,$latitude"; my $j = LWP::Simple::get($url); if ($j) { $j = JSON->new->utf8->allow_nonref->decode($j); if ($j->{postcode}) { $str .= sprintf(_("Nearest postcode to the pin placed on the map (automatically generated): %s (%sm away)"), - $j->{postcode}[0], $j->{postcode}[1]) . "\n\n"; + $j->{postcode}{postcode}, $j->{postcode}{distance}) . "\n\n"; } } diff --git a/perllib/FixMyStreet/DB/Result/Contact.pm b/perllib/FixMyStreet/DB/Result/Contact.pm index 2a6ffa2fe..993e3524b 100644 --- a/perllib/FixMyStreet/DB/Result/Contact.pm +++ b/perllib/FixMyStreet/DB/Result/Contact.pm @@ -36,6 +36,8 @@ __PACKAGE__->add_columns( { data_type => "text", is_nullable => 0 }, "extra", { data_type => "text", is_nullable => 1 }, + "non_public", + { data_type => "boolean", default_value => \"false", is_nullable => 1 }, "endpoint", { data_type => "text", is_nullable => 1 }, "jurisdiction", @@ -49,8 +51,8 @@ __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("contacts_area_id_category_idx", ["area_id", "category"]); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-29 17:34:28 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:getDAgTeXkAYQTcxHWflmA +# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-31 10:29:17 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:t6yOPhZmedV/eH6AUvHI6w __PACKAGE__->filter_column( extra => { diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index af62a299b..761f57b01 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -92,6 +92,8 @@ __PACKAGE__->add_columns( { data_type => "timestamp", is_nullable => 1 }, "send_method_used", { data_type => "text", is_nullable => 1 }, + "non_public", + { data_type => "boolean", default_value => \"false", is_nullable => 1 }, "external_source", { data_type => "text", is_nullable => 1 }, "external_source_id", @@ -120,8 +122,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-23 12:14:00 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:05LIWlb0CUWAR7bN5RAhOA +# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-31 10:25:34 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mudIAiLAUdmK8gGWIPiq6g # Add fake relationship to stored procedure table __PACKAGE__->has_one( diff --git a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm index a0320ccc3..2d206d84e 100644 --- a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm +++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm @@ -65,6 +65,9 @@ sub email_alerts ($) { # call checks if this is the host that sends mail for this cobrand. next unless $cobrand->email_host; + # this is for the new_updates alerts + next if $row->{non_public} and $row->{user_id} != $row->{alert_user_id}; + my $hashref_restriction = $cobrand->site_restriction( $row->{cobrand_data} ); FixMyStreet::App->model('DB::AlertSent')->create( { @@ -151,6 +154,7 @@ sub email_alerts ($) { where nearby.problem_id = problem.id and problem.user_id = users.id and problem.state in ($states) + and problem.non_public = 'f' and problem.confirmed >= ? and problem.confirmed >= ms_current_timestamp() - '7 days'::interval and (select whenqueued from alert_sent where alert_sent.alert_id = ? and alert_sent.parameter::integer = problem.id) is null and users.email <> ? diff --git a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm index 83fc85a88..191223572 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm @@ -8,6 +8,7 @@ sub nearby { my ( $rs, $c, $dist, $ids, $limit, $mid_lat, $mid_lon, $interval ) = @_; my $params = { + non_public => 0, state => [ FixMyStreet::DB::Result::Problem::visible_states() ], }; $params->{'current_timestamp-lastupdate'} = { '<', \"'$interval'::interval" } diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm index e946e01c2..f7f88edf0 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm @@ -85,7 +85,8 @@ sub _recent { $key .= ":$site_key:$num"; my $query = { - state => [ FixMyStreet::DB::Result::Problem->visible_states() ], + non_public => 0, + state => [ FixMyStreet::DB::Result::Problem->visible_states() ], }; $query->{photo} = { '!=', undef } if $photos; @@ -141,6 +142,7 @@ sub around_map { $attr->{rows} = $limit if $limit; my $q = { + non_public => 0, state => [ FixMyStreet::DB::Result::Problem->visible_states() ], latitude => { '>=', $min_lat, '<', $max_lat }, longitude => { '>=', $min_lon, '<', $max_lon }, diff --git a/perllib/FixMyStreet/Geocode/OSM.pm b/perllib/FixMyStreet/Geocode/OSM.pm index ba939b443..78db7fe44 100644 --- a/perllib/FixMyStreet/Geocode/OSM.pm +++ b/perllib/FixMyStreet/Geocode/OSM.pm @@ -15,9 +15,10 @@ use Digest::MD5 qw(md5_hex); use Encode; use File::Slurp; use File::Path (); -use LWP::Simple; +use LWP::Simple qw($ua); use Memcached; use XML::Simple; +use mySociety::Locale; my $osmapibase = "http://www.openstreetmap.org/api/"; my $nominatimbase = "http://nominatim.openstreetmap.org/"; @@ -49,6 +50,7 @@ sub string { if (-s $cache_file) { $js = File::Slurp::read_file($cache_file); } else { + $ua->timeout(15); $js = LWP::Simple::get($url); $js = encode_utf8($js) if utf8::is_utf8($js); File::Path::mkpath($cache_dir); diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm index 2a49cc2f8..5866ee21c 100644 --- a/perllib/FixMyStreet/TestMech.pm +++ b/perllib/FixMyStreet/TestMech.pm @@ -378,6 +378,49 @@ sub extract_update_metas { return \@metas; } +=head2 extract_problem_list + + $problems = $mech->extract_problem_list + +Returns an array ref of all problem titles on a page featuring standard issue lists + +=cut + +sub extract_problem_list { + my $mech = shift; + + my $result = scraper { + process 'ul.issue-list-a li a h4', 'problems[]', 'TEXT'; + }->scrape( $mech->response ); + + return $result->{ problems } || []; +} + +=head2 extract_report_stats + + $stats = $mech->extract_report_stats + +Returns a hash ref keyed by council name of all the council stats from the all reports +page. Each value is an array ref with the first element being the council name and the +rest being the stats in the order the appear in each row. + +=cut + +sub extract_report_stats { + my $mech = shift; + + my $result = scraper { + process 'tr[align=center]', 'councils[]' => scraper { + process 'td.title a', 'council', 'TEXT', + process 'td', 'stats[]', 'TEXT' + } + }->scrape( $mech->response ); + + my %councils = map { $_->{council} => $_->{stats} } @{ $result->{councils} }; + + return \%councils; +} + =head2 visible_form_values $hashref = $mech->visible_form_values( ); @@ -475,4 +518,67 @@ sub get_ok_json { return decode_json( $res->content ); } +sub delete_problems_for_council { + my $mech = shift; + my $council = shift; + + my $reports = FixMyStreet::App->model('DB::Problem')->search( { council => $council } ); + if ( $reports ) { + for my $r ( $reports->all ) { + $r->comments->delete; + } + $reports->delete; + } +} + +sub create_problems_for_council { + my ( $mech, $count, $council, $title, $params ) = @_; + + my $dt = $params->{dt} || DateTime->now(); + + my $user = $params->{user} || + FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'test@example.com', name => 'Test User' } ); + + delete $params->{user}; + delete $params->{dt}; + + my @problems; + + while ($count) { + my $default_params = { + postcode => 'SW1A 1AA', + council => $council, + areas => ',105255,11806,11828,2247,2504,', + category => 'Other', + title => "$title Test $count for $council", + detail => "$title Test $count for $council Detail", + used_map => 't', + name => 'Test User', + anonymous => 'f', + state => 'confirmed', + confirmed => $dt->ymd . ' ' . $dt->hms, + lang => 'en-gb', + service => '', + cobrand => 'default', + cobrand_data => '', + send_questionnaire => 't', + latitude => '51.5016605453401', + longitude => '-0.142497580865087', + user_id => $user->id, + photo => 1, + }; + + my %report_params = ( %$default_params, %$params ); + + my $problem = + FixMyStreet::App->model('DB::Problem')->create( \%report_params ); + + push @problems, $problem; + $count--; + } + + return @problems; +} + 1; diff --git a/perllib/Open311.pm b/perllib/Open311.pm index aa0e64b53..1027c756f 100644 --- a/perllib/Open311.pm +++ b/perllib/Open311.pm @@ -65,7 +65,11 @@ sub send_service_request { if ( $obj ) { if ( $obj->{ request }->{ service_request_id } ) { - return $obj->{ request }->{ service_request_id }; + my $request_id = $obj->{request}->{service_request_id}; + + unless ( ref $request_id ) { + return $request_id; + } } else { my $token = $obj->{ request }->{ token }; if ( $token ) { @@ -75,8 +79,10 @@ sub send_service_request { } warn sprintf( "Failed to submit problem %s over Open311, response\n: %s\n%s", $problem->id, $response, $self->debug_details ); - return 0; + } else { + warn sprintf( "Failed to submit problem %s over Open311, details:\n%s", $problem->id, $self->error); } + return 0; } sub _populate_service_request_params { @@ -259,8 +265,10 @@ sub post_service_request_update { } warn sprintf( "Failed to submit comment %s over Open311, response - %s\n%s\n", $comment->id, $response, $self->debug_details ); - return 0; + } else { + warn sprintf( "Failed to submit comment %s over Open311, details\n%s\n", $comment->id, $self->error); } + return 0; } sub _populate_service_request_update_params { @@ -379,7 +387,6 @@ sub _post { $self->_process_error( $res->decoded_content ), $self->debug_details ) ); - warn $self->error; return 0; } } diff --git a/perllib/Utils.pm b/perllib/Utils.pm index 6a47fd17d..23a87485d 100644 --- a/perllib/Utils.pm +++ b/perllib/Utils.pm @@ -159,7 +159,6 @@ sub barnet_categories { } } else { return { - 'Abandoned Vehicle' => 468, 'Accumulated Litter' => 349, 'Dog Bin' => 203, 'Dog Fouling' => 288, diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t index 09d99cfdf..839bfd6b9 100644 --- a/t/app/controller/admin.t +++ b/t/app/controller/admin.t @@ -163,19 +163,32 @@ subtest 'check contact creation' => sub { $mech->get_ok('/admin/council_contacts/2650'); $mech->submit_form_ok( { with_fields => { - category => 'test category', - email => 'test@example.com', - note => 'test note', + category => 'test category', + email => 'test@example.com', + note => 'test note', + non_public => undef, } } ); $mech->content_contains( 'test category' ); $mech->content_contains( '<td>test@example.com' ); $mech->content_contains( '<td>test note' ); + $mech->content_contains( '<td>Public' ); + + $mech->submit_form_ok( { with_fields => { + category => 'private category', + email => 'test@example.com', + note => 'test note', + non_public => 'on', + } } ); + + $mech->content_contains( 'private category' ); + $mech->content_contains( '<td>Non Public' ); $mech->submit_form_ok( { with_fields => { category => 'test/category', email => 'test@example.com', note => 'test/note', + non_public => 'on', } } ); $mech->get_ok('/admin/council_edit/2650/test/category'); @@ -187,11 +200,21 @@ subtest 'check contact editing' => sub { $mech->submit_form_ok( { with_fields => { email => 'test2@example.com', note => 'test2 note', + non_public => undef, } } ); $mech->content_contains( 'test category' ); $mech->content_contains( '<td>test2@example.com' ); $mech->content_contains( '<td>test2 note' ); + $mech->content_contains( '<td>Public' ); + + $mech->submit_form_ok( { with_fields => { + email => 'test2@example.com', + note => 'test2 note', + non_public => 'on', + } } ); + + $mech->content_contains( '<td>Non Public' ); $mech->get_ok('/admin/council_edit/2650/test%20category'); $mech->content_contains( '<td><strong>test2@example.com' ); @@ -293,206 +316,229 @@ ok $report, "created test report - $report_id"; foreach my $test ( { description => 'edit report title', - fields => { - title => 'Report to Edit', - detail => 'Detail for Report to Edit', - state => 'confirmed', - name => 'Test User', - email => $user->email, - anonymous => 0, - flagged => undef, - }, - changes => { - title => 'Edited Report', + fields => { + title => 'Report to Edit', + detail => 'Detail for Report to Edit', + state => 'confirmed', + name => 'Test User', + email => $user->email, + anonymous => 0, + flagged => undef, + non_public => undef, }, - log_count => 1, - log_entries => [ qw/edit/ ], - resend => 0, + changes => { title => 'Edited Report', }, + log_count => 1, + log_entries => [qw/edit/], + resend => 0, }, { description => 'edit report description', - fields => { - title => 'Edited Report', - detail => 'Detail for Report to Edit', - state => 'confirmed', - name => 'Test User', - email => $user->email, - anonymous => 0, - flagged => undef, + fields => { + title => 'Edited Report', + detail => 'Detail for Report to Edit', + state => 'confirmed', + name => 'Test User', + email => $user->email, + anonymous => 0, + flagged => undef, + non_public => undef, }, - changes => { - detail => 'Edited Detail', - }, - log_count => 2, - log_entries => [ qw/edit edit/ ], - resend => 0, + changes => { detail => 'Edited Detail', }, + log_count => 2, + log_entries => [qw/edit edit/], + resend => 0, }, { description => 'edit report user name', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'confirmed', - name => 'Test User', - email => $user->email, - anonymous => 0, - flagged => undef, - }, - changes => { - name => 'Edited User', + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Test User', + email => $user->email, + anonymous => 0, + flagged => undef, + non_public => undef, }, - log_count => 3, - log_entries => [ qw/edit edit edit/ ], - resend => 0, - user => $user, + changes => { name => 'Edited User', }, + log_count => 3, + log_entries => [qw/edit edit edit/], + resend => 0, + user => $user, }, { description => 'edit report set flagged true', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'confirmed', - name => 'Edited User', - email => $user->email, - anonymous => 0, - flagged => undef, + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Edited User', + email => $user->email, + anonymous => 0, + flagged => undef, + non_public => undef, }, changes => { - flagged => 'on', + flagged => 'on', }, - log_count => 4, - log_entries => [ qw/edit edit edit edit/ ], - resend => 0, - user => $user, + log_count => 4, + log_entries => [qw/edit edit edit edit/], + resend => 0, + user => $user, }, { description => 'edit report user email', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'confirmed', - name => 'Edited User', - email => $user->email, - anonymous => 0, - flagged => 'on', - }, - changes => { - email => $user2->email, + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Edited User', + email => $user->email, + anonymous => 0, + flagged => 'on', + non_public => undef, }, - log_count => 5, - log_entries => [ qw/edit edit edit edit edit/ ], - resend => 0, - user => $user2, + changes => { email => $user2->email, }, + log_count => 5, + log_entries => [qw/edit edit edit edit edit/], + resend => 0, + user => $user2, }, { description => 'change state to unconfirmed', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'confirmed', - name => 'Edited User', - email => $user2->email, - anonymous => 0, - flagged => 'on', - }, - changes => { - state => 'unconfirmed' + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Edited User', + email => $user2->email, + anonymous => 0, + flagged => 'on', + non_public => undef, }, + changes => { state => 'unconfirmed' }, log_count => 6, - log_entries => [ qw/state_change edit edit edit edit edit/ ], - resend => 0, + log_entries => [qw/state_change edit edit edit edit edit/], + resend => 0, }, { description => 'change state to confirmed', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'unconfirmed', - name => 'Edited User', - email => $user2->email, - anonymous => 0, - flagged => 'on', - }, - changes => { - state => 'confirmed' + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'unconfirmed', + name => 'Edited User', + email => $user2->email, + anonymous => 0, + flagged => 'on', + non_public => undef, }, + changes => { state => 'confirmed' }, log_count => 7, - log_entries => [ qw/state_change state_change edit edit edit edit edit/ ], - resend => 0, + log_entries => [qw/state_change state_change edit edit edit edit edit/], + resend => 0, }, { description => 'change state to fixed', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'confirmed', - name => 'Edited User', - email => $user2->email, - anonymous => 0, - flagged => 'on', - }, - changes => { - state => 'fixed' + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Edited User', + email => $user2->email, + anonymous => 0, + flagged => 'on', + non_public => undef, }, + changes => { state => 'fixed' }, log_count => 8, - log_entries => [ qw/state_change state_change state_change edit edit edit edit edit/ ], + log_entries => + [qw/state_change state_change state_change edit edit edit edit edit/], resend => 0, }, { description => 'change state to hidden', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'fixed', - name => 'Edited User', - email => $user2->email, - anonymous => 0, - flagged => 'on', - }, - changes => { - state => 'hidden' + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'fixed', + name => 'Edited User', + email => $user2->email, + anonymous => 0, + flagged => 'on', + non_public => undef, }, - log_count => 9, - log_entries => [ qw/state_change state_change state_change state_change edit edit edit edit edit/ ], + changes => { state => 'hidden' }, + log_count => 9, + log_entries => [ + qw/state_change state_change state_change state_change edit edit edit edit edit/ + ], resend => 0, }, { description => 'edit and change state', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'hidden', - name => 'Edited User', - email => $user2->email, - anonymous => 0, - flagged => 'on', + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'hidden', + name => 'Edited User', + email => $user2->email, + anonymous => 0, + flagged => 'on', + non_public => undef, }, changes => { - state => 'confirmed', + state => 'confirmed', anonymous => 1, }, - log_count => 11, - log_entries => [ qw/edit state_change state_change state_change state_change state_change edit edit edit edit edit/ ], + log_count => 11, + log_entries => [ + qw/edit state_change state_change state_change state_change state_change edit edit edit edit edit/ + ], resend => 0, }, { description => 'resend', - fields => { - title => 'Edited Report', - detail => 'Edited Detail', - state => 'confirmed', - name => 'Edited User', - email => $user2->email, - anonymous => 1, - flagged => 'on', - }, - changes => { + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Edited User', + email => $user2->email, + anonymous => 1, + flagged => 'on', + non_public => undef, }, - log_count => 12, - log_entries => [ qw/resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/ ], + changes => {}, + log_count => 12, + log_entries => [ + qw/resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/ + ], resend => 1, }, -) { + { + description => 'non public', + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Edited User', + email => $user2->email, + anonymous => 1, + flagged => 'on', + non_public => undef, + }, + changes => { + non_public => 'on', + }, + log_count => 13, + log_entries => [ + qw/edit resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/ + ], + resend => 0, + }, + ) +{ subtest $test->{description} => sub { $log_entries->reset; $mech->get_ok("/admin/report_edit/$report_id"); @@ -523,6 +569,8 @@ foreach my $test ( } $test->{changes}->{flagged} = 1 if $test->{changes}->{flagged}; + $test->{changes}->{non_public} = 1 if $test->{changes}->{non_public}; + is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'email' } keys %{ $test->{changes} }; if ( $test->{user} ) { @@ -547,6 +595,7 @@ subtest 'change email to new user' => sub { email => $report->user->email, anonymous => 1, flagged => 'on', + non_public => 'on', }; is_deeply( $mech->visible_form_values(), $fields, 'initial form values' ); diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index d66590c57..cb787d959 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -464,4 +464,194 @@ subtest "Test normal alert signups and that alerts are sent" => sub { $mech->delete_user($user2); }; +for my $test ( + { + desc => 'check non public reports are not included in council problems alerts', + alert_params => { + alert_type => 'council_problems', + parameter => '2651', + parameter2 => '2651', + } + }, + { + desc => 'check non public reports are not included in ward problems alerts', + alert_params => { + alert_type => 'ward_problems', + parameter => '2651', + parameter2 => '20728', + } + }, + { + desc => 'check non public reports are not included in local problems alerts', + alert_params => { + alert_type => 'local_problems', + parameter => '-3.189944', + parameter2 => '55.951963', + } + }, + { + desc => 'check non public reports are not included in area problems alerts', + alert_params => { + alert_type => 'area_problems', + parameter => '20728', + parameter2 => '20728', + } + }, +) { + subtest $test->{desc} => sub { + my $user1 = FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'reporter@example.com', name => 'Reporter User' } ); + ok $user1, "created test user"; + $user1->alerts->delete; + + my $user2 = FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'alerts@example.com', name => 'Alert User' } ); + ok $user2, "created test user"; + $user2->alerts->delete; + + my $dt = DateTime->now->add( minutes => -30 ); + my $r_dt = $dt->clone->add( minutes => 20 ); + + my $alert_params = $test->{alert_params}; + $alert_params->{user} = $user1; + $alert_params->{whensubscribed} = $dt; + $alert_params->{confirmed} = 1; + + my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( $alert_params ); + ok $alert_user1, "alert created"; + + my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { + postcode => 'EH1 1BB', + council => '2651', + areas => ',11808,135007,14419,134935,2651,20728,', + category => 'Street lighting', + title => 'Alert test for non public reports', + detail => 'Testing Detail', + used_map => 1, + name => $user2->name, + anonymous => 0, + state => 'confirmed', + confirmed => $r_dt, + lastupdate => $r_dt, + whensent => $r_dt->clone->add( minutes => 5 ), + lang => 'en-gb', + service => '', + cobrand => 'default', + cobrand_data => '', + send_questionnaire => 1, + latitude => '55.951963', + longitude => '-3.189944', + user_id => $user2->id, + non_public => 1, + } ); + + $mech->clear_emails_ok; + FixMyStreet::App->model('DB::AlertType')->email_alerts(); + $mech->email_count_is(0); + + $report->update( { non_public => 0 } ); + FixMyStreet::App->model('DB::AlertType')->email_alerts(); + $mech->email_count_is(1); + my $email = $mech->get_email; + like $email->body, qr/Alert\s+test\s+for\s+non\s+public\s+reports/, 'alert contains public report'; + + $mech->delete_user( $user1 ); + $mech->delete_user( $user2 ); + }; +} + +subtest 'check new updates alerts for non public reports only go to report owner' => sub { + my $user1 = FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'reporter@example.com', name => 'Reporter User' } ); + ok $user1, "created test user"; + $user1->alerts->delete; + + my $user2 = FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'alerts@example.com', name => 'Alert User' } ); + ok $user2, "created test user"; + $user2->alerts->delete; + + my $user3 = FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'updates@example.com', name => 'Update User' } ); + ok $user3, "created test user"; + + my $dt = DateTime->now->add( minutes => -30 ); + my $r_dt = $dt->clone->add( minutes => 20 ); + + my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { + postcode => 'EH1 1BB', + council => '2651', + areas => ',11808,135007,14419,134935,2651,20728,', + category => 'Street lighting', + title => 'Alert test for non public reports', + detail => 'Testing Detail', + used_map => 1, + name => $user2->name, + anonymous => 0, + state => 'confirmed', + confirmed => $r_dt, + lastupdate => $r_dt, + whensent => $r_dt->clone->add( minutes => 5 ), + lang => 'en-gb', + service => '', + cobrand => 'default', + cobrand_data => '', + send_questionnaire => 1, + latitude => '55.951963', + longitude => '-3.189944', + user_id => $user2->id, + non_public => 1, + } ); + + my $update = FixMyStreet::App->model('DB::Comment')->create( { + problem_id => $report->id, + user_id => $user3->id, + name => 'Anonymous User', + mark_fixed => 'false', + text => 'This is some more update text', + state => 'confirmed', + confirmed => $r_dt->clone->add( minutes => 8 ), + anonymous => 't', + } ); + + my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( { + user => $user1, + alert_type => 'new_updates', + parameter => $report->id, + confirmed => 1, + whensubscribed => $dt, + } ); + ok $alert_user1, "alert created"; + + + $mech->clear_emails_ok; + FixMyStreet::App->model('DB::AlertType')->email_alerts(); + $mech->email_count_is(0); + + my $alert_user2 = FixMyStreet::App->model('DB::Alert')->create( { + user => $user2, + alert_type => 'new_updates', + parameter => $report->id, + confirmed => 1, + whensubscribed => $dt, + } ); + ok $alert_user2, "alert created"; + + FixMyStreet::App->model('DB::AlertType')->email_alerts(); + $mech->email_count_is(1); + my $email = $mech->get_email; + like $email->body, qr/This is some more update text/, 'alert contains update text'; + + $mech->clear_emails_ok; + $report->update( { non_public => 0 } ); + FixMyStreet::App->model('DB::AlertType')->email_alerts(); + $mech->email_count_is(1); + $email = $mech->get_email; + like $email->body, qr/This is some more update text/, 'alert contains update text'; + + $mech->delete_user( $user1 ); + $mech->delete_user( $user2 ); + $mech->delete_user( $user3 ); +}; + done_testing(); diff --git a/t/app/controller/around.t b/t/app/controller/around.t index db03e00f4..e1c76ff9f 100644 --- a/t/app/controller/around.t +++ b/t/app/controller/around.t @@ -78,4 +78,30 @@ foreach my $test ( }; } +subtest 'check non public reports are not displayed on around page' => sub { + my $params = { + postcode => 'EH99 1SP', + latitude => 55.9519637512, + longitude => -3.17492254484, + }; + my @edinburgh_problems = + $mech->create_problems_for_council( 5, 2651, 'Around page', $params ); + + $mech->get_ok('/'); + $mech->submit_form_ok( { with_fields => { pc => 'EH99 1SP' } }, + "good location" ); + $mech->content_contains( 'Around page Test 3 for 2651', + 'problem to be marked non public visible' ); + + my $private = $edinburgh_problems[2]; + ok $private->update( { non_public => 1 } ), 'problem marked non public'; + + $mech->get_ok('/'); + $mech->submit_form_ok( { with_fields => { pc => 'EH99 1SP' } }, + "good location" ); + $mech->content_lacks( 'Around page Test 3 for 2651', + 'problem marked non public is not visible' ); +}; + + done_testing(); diff --git a/t/app/controller/index.t b/t/app/controller/index.t index bf9124ee0..462b21064 100644 --- a/t/app/controller/index.t +++ b/t/app/controller/index.t @@ -55,4 +55,23 @@ subtest "does pc, (x,y), (e,n) or (lat,lon) go to /around" => sub { } }; +$mech->delete_problems_for_council( 2651 ); + +my $problem_rs = FixMyStreet::App->model('DB::Problem'); +my $num = $problem_rs->count; + +my @edinburgh_problems = $mech->create_problems_for_council(5, 2651, 'Front page'); +is scalar @edinburgh_problems, 5, 'correct number of edinburgh problems created'; + +$mech->get_ok('/report/' . $edinburgh_problems[2]->id); +$mech->content_contains('Front page Test 3 for 2651', 'problem to be marked non public visible'); +is $problem_rs->count, $num+5; + +my $private = $edinburgh_problems[2]; +ok $private->update( { non_public => 1 } ), 'problem marked non public'; + +ok $mech->get('/report/' . $edinburgh_problems[2]->id); +is $mech->res->code, 403, 'page forbidden'; +is $problem_rs->count, $num+5; + done_testing(); diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t index 6c2733e36..3bb0913f1 100644 --- a/t/app/controller/report_display.t +++ b/t/app/controller/report_display.t @@ -16,6 +16,11 @@ my $user = ->find_or_create( { email => 'test@example.com', name => 'Test User' } ); ok $user, "created test user"; +my $user2 = + FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'test2@example.com', name => 'Other User' } ); +ok $user2, "created test user"; + my $dt = DateTime->new( year => 2011, month => 04, @@ -98,6 +103,32 @@ subtest "change report to hidden and check for 410 status" => sub { ok $report->update( { state => 'confirmed' } ), 'confirm report again'; }; +subtest "change report to non_public and check for 403 status" => sub { + ok $report->update( { non_public => 1 } ), 'make report non public'; + ok $mech->get("/report/$report_id"), "get '/report/$report_id'"; + is $mech->res->code, 403, "access denied"; + is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; + $mech->content_contains('That report cannot be viewed on FixMyStreet.'); + ok $report->update( { non_public => 0 } ), 'make report public'; +}; + +subtest "check owner of report can view non public reports" => sub { + ok $report->update( { non_public => 1 } ), 'make report non public'; + $mech->log_in_ok( $report->user->email ); + ok $mech->get("/report/$report_id"), "get '/report/$report_id'"; + is $mech->res->code, 200, "report can be viewed"; + is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; + $mech->log_out_ok; + + $mech->log_in_ok( $user2->email ); + ok $mech->get("/report/$report_id"), "get '/report/$report_id'"; + is $mech->res->code, 403, "access denied to user who is not report creator"; + is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; + $mech->content_contains('That report cannot be viewed on FixMyStreet.'); + $mech->log_out_ok; + ok $report->update( { non_public => 0 } ), 'make report public'; +}; + subtest "test a good report" => sub { $mech->get_ok("/report/$report_id"); is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t index 88236a1c3..2e7e60f75 100644 --- a/t/app/controller/report_new.t +++ b/t/app/controller/report_new.t @@ -788,6 +788,74 @@ foreach my $test ( } +subtest "test report creation for a category that is non public" => sub { + $mech->log_out_ok; + $mech->clear_emails_ok; + + # check that the user does not exist + my $test_email = 'test-2@example.com'; + + my $user = FixMyStreet::App->model('DB::User')->find_or_create( { email => $test_email } ); + ok $user, "test user does exist"; + + $contact1->update( { non_public => 1 } ); + + # submit initial pc form + $mech->get_ok('/around'); + $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB', } }, + "submit location" ); + + # click through to the report page + $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, + "follow 'skip this step' link" ); + + $mech->submit_form_ok( + { + button => 'submit_register', + with_fields => { + title => 'Test Report', + detail => 'Test report details.', + photo => '', + email => 'test-2@example.com', + name => 'Joe Bloggs', + category => 'Street lighting', + } + }, + "submit good details" + ); + + # find the report + my $report = $user->problems->first; + ok $report, "Found the report"; + + # Check the report is not public + ok $report->non_public, 'report is not public'; + + my $email = $mech->get_email; + ok $email, "got an email"; + like $email->body, qr/confirm the problem/i, "confirm the problem"; + + my ($url) = $email->body =~ m{(http://\S+)}; + ok $url, "extracted confirm url '$url'"; + + # confirm token + $mech->get_ok($url); + $report->discard_changes; + + is $report->state, 'confirmed', "Report is now confirmed"; + + $mech->logged_in_ok; + $mech->get_ok( '/report/' . $report->id, 'user can see own report' ); + + $mech->log_out_ok; + ok $mech->get("/report/" . $report->id), "fetched report"; + is $mech->res->code, 403, "access denied to report"; + + # cleanup + $mech->delete_user($user); + $contact1->update( { non_public => 0 } ); +}; + $contact2->category( "Pothol\xc3\xa9s" ); $contact2->update; $mech->get_ok( '/report/new/ajax?latitude=' . $saved_lat . '&longitude=' . $saved_lon ); @@ -970,6 +1038,7 @@ SKIP: { $mech->log_out_ok; $mech->get_ok('/around'); + $mech->content_contains( "Lichfield District Council FixMyStreet" ); $mech->submit_form_ok( { with_fields => { pc => 'WS13 7RD' } }, "submit location" ); $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" ); $mech->submit_form_ok( diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t index cf6af16cb..82670d6cc 100644 --- a/t/app/controller/report_updates.t +++ b/t/app/controller/report_updates.t @@ -577,7 +577,12 @@ for my $test ( is $update->problem_state, $test->{state}, 'problem state set'; my $update_meta = $mech->extract_update_metas; - like $update_meta->[0], qr/marked as $test->{fields}->{state}$/, 'update meta includes state change'; + # setting it to confirmed shouldn't say anything + if ( $test->{fields}->{state} ne 'confirmed' ) { + like $update_meta->[0], qr/marked as $test->{fields}->{state}$/, 'update meta includes state change'; + } else { + like $update_meta->[0], qr/reopened$/, 'update meta includes state change'; + } like $update_meta->[0], qr{Test User \(Westminster City Council\)}, 'update meta includes council name'; $mech->content_contains( 'Test User (<strong>Westminster City Council</strong>)', 'council name in bold'); @@ -586,6 +591,44 @@ for my $test ( }; } +subtest 'check meta correct for comments marked confirmed but not marked open' => sub { + $report->comments->delete; + my $comment = FixMyStreet::App->model('DB::Comment')->create( + { + user => $user, + problem_id => $report->id, + text => 'update text', + confirmed => DateTime->now, + problem_state => 'confirmed', + anonymous => 0, + mark_open => 0, + mark_fixed => 0, + state => 'confirmed', + } + ); + + $mech->get_ok( "/report/" . $report->id ); + my $update_meta = $mech->extract_update_metas; + like $update_meta->[0], qr/reopened$/, + 'update meta does not say reopened'; + + $comment->update( { mark_open => 1, problem_state => undef } ); + $mech->get_ok( "/report/" . $report->id ); + $update_meta = $mech->extract_update_metas; + + unlike $update_meta->[0], qr/marked as open$/, + 'update meta does not says marked as open'; + like $update_meta->[0], qr/reopened$/, 'update meta does say reopened'; + + $comment->update( { mark_open => 0, problem_state => undef } ); + $mech->get_ok( "/report/" . $report->id ); + $update_meta = $mech->extract_update_metas; + + unlike $update_meta->[0], qr/marked as open$/, + 'update meta does not says marked as open'; + unlike $update_meta->[0], qr/reopened$/, 'update meta does not say reopened'; + }; + $user->from_council(0); $user->update; diff --git a/t/app/controller/reports.t b/t/app/controller/reports.t index 801dbeddb..a4dab6597 100644 --- a/t/app/controller/reports.t +++ b/t/app/controller/reports.t @@ -1,10 +1,21 @@ use strict; use warnings; use Test::More; -use Test::WWW::Mechanize::Catalyst 'FixMyStreet::App'; +use FixMyStreet::TestMech; use mySociety::MaPit; +use FixMyStreet::App; +use DateTime; -ok( my $mech = Test::WWW::Mechanize::Catalyst->new, 'Created mech object' ); +ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' ); + +$mech->delete_problems_for_council( 2504 ); +$mech->delete_problems_for_council( 2651 ); + +my @edinburgh_problems = $mech->create_problems_for_council(3, 2651, 'All reports'); +my @westminster_problems = $mech->create_problems_for_council(5, 2504, 'All reports'); + +is scalar @westminster_problems, 5, 'correct number of westminster problems created'; +is scalar @edinburgh_problems, 3, 'correct number of edinburgh problems created'; # Run the cron script that makes the data for /reports so we don't get an error. system( "bin/cron-wrapper update-all-reports" ); @@ -13,8 +24,35 @@ system( "bin/cron-wrapper update-all-reports" ); $mech->get_ok('/reports'); $mech->title_like(qr{Summary reports}); $mech->content_contains('Birmingham'); + +my $stats = $mech->extract_report_stats; + +is $stats->{'City of Edinburgh Council'}->[1], 3, 'correct number of reports for Edinburgh'; +is $stats->{'Westminster City Council'}->[1], 5, 'correct number of reports for Westminster'; + $mech->follow_link_ok( { text_regex => qr/Birmingham/ } ); +$mech->get_ok('/reports/Westminster'); +$mech->title_like(qr/Westminster City Council/); +$mech->content_contains('Westminster City Council'); +$mech->content_contains('All reports Test 3 for 2504', 'problem to be marked non public visible'); + +my $problems = $mech->extract_problem_list; +is scalar @$problems, 5, 'correct number of problems displayed'; + +my $private = $westminster_problems[2]; +ok $private->update( { non_public => 1 } ), 'problem marked non public'; + +$mech->get_ok('/reports/Westminster'); +$problems = $mech->extract_problem_list; +is scalar @$problems, 4, 'only public problems are displayed'; + +$mech->content_lacks('All reports Test 3 for 2504', 'non public problem is not visible'); + +$mech->get_ok('/reports'); +$stats = $mech->extract_report_stats; +is $stats->{'Westminster City Council'}->[1], 5, 'non public reports included in stats'; + SKIP: { skip( "Need 'emptyhomes' in ALLOWED_COBRANDS config", 8 ) unless FixMyStreet::Cobrand->exists('emptyhomes'); diff --git a/t/cobrand/closest.t b/t/cobrand/closest.t index 02c979756..464c95e67 100644 --- a/t/cobrand/closest.t +++ b/t/cobrand/closest.t @@ -54,7 +54,7 @@ ok $report, "created test report - $report_id"; $report->geocode( undef ); -ok !$report->geocode, 'no gecode entry for report'; +ok !$report->geocode, 'no geocode entry for report'; my $near = $c->find_closest( $report->latitude, $report->longitude, $report ); diff --git a/t/open311.t b/t/open311.t index f082179ea..ce0a4ed90 100644 --- a/t/open311.t +++ b/t/open311.t @@ -37,9 +37,10 @@ my $p = FixMyStreet::App->model('DB::Problem')->new( { title => 'title', detail => 'detail', user => $u, + id => 1, } ); -my $expected_error = qr{.*request failed: 500 Can.t connect to 192.168.50.1:80 \([^)]*\).*}; +my $expected_error = qr{Failed to submit problem 1 over Open311}ism; warning_like {$o2->send_service_request( $p, { url => 'http://example.com/' }, 1 )} $expected_error, 'warning generated on failed call'; @@ -410,20 +411,48 @@ for my $test ( }; } +subtest 'No request id in reponse' => sub { + my $results; + warning_like { + $results = make_service_req( + $problem, + { url => 'http://example.com/report/1' }, + $problem->category, + '<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id></service_request_id></request></service_requests>' + ); + } qr/Failed to submit problem \d+ over Open311/, 'correct error message for missing request_id'; + + is $results->{ res }, 0, 'No request_id is a failure'; +}; + +subtest 'Bad data in request_id element in reponse' => sub { + my $results; + warning_like { + $results = make_service_req( + $problem, + { url => 'http://example.com/report/1' }, + $problem->category, + '<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id><bad_data>BAD</bad_data></service_request_id></request></service_requests>' + ); + } qr/Failed to submit problem \d+ over Open311/, 'correct error message for bad data in request_id'; + + is $results->{ res }, 0, 'No request_id is a failure'; +}; + subtest 'No update id in reponse' => sub { my $results; warning_like { $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id></update_id></request_update></service_request_updates>' ) - } qr/Failed to submit comment \d+ over Open311/, 'correct error message'; + } qr/Failed to submit comment \d+ over Open311/, 'correct error message for missing update_id'; is $results->{ res }, 0, 'No update_id is a failure'; }; -subtest 'error reponse' => sub { +subtest 'error response' => sub { my $results; warning_like { $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><errors><error><code>400</code><description>There was an error</description</error></errors>' ) - } qr/Failed to submit comment \d+ over Open311.*There was an error/, 'correct error messages'; + } qr/Failed to submit comment \d+ over Open311.*There was an error/, 'correct error messages for general error'; is $results->{ res }, 0, 'error in response is a failure'; }; diff --git a/templates/web/default/admin/council_contacts.html b/templates/web/default/admin/council_contacts.html index 7f23a442d..eb9606a31 100644 --- a/templates/web/default/admin/council_contacts.html +++ b/templates/web/default/admin/council_contacts.html @@ -41,6 +41,7 @@ <th>[% loc('Devolved') %]</th> <th>[% loc('Last editor') %]</th> <th>[% loc('Note') %]</th> + <th>[% loc('Public') %]</th> <th>[% loc('When edited') %]</th> <th>[% loc('Confirm') %]</th> </tr> @@ -53,6 +54,7 @@ <td>[% IF conf.can_be_devolved && contact.send_method %][% loc('Yes') %][% ELSE %][% loc('No') %][% END %]</td> <td>[% contact.editor %]</td> <td>[% contact.note | html %]</td> + <td>[% contact.non_public ? loc('Non Public') : loc('Public') %]</td> <td>[% contact.whenedited.ymd _ ' ' _ contact.whenedited.hms %]</td> <td><input type="checkbox" name="confirmed" value="[% contact.category %]"></td> </tr> @@ -85,7 +87,7 @@ <input type="checkbox" name="confirmed" value="1" id="confirmed"> <label for="confirmed">[% loc('Confirmed') %]</label> - <input type="checkbox" name="deleted" value="1"id="deleted"> + <input type="checkbox" name="deleted" value="1" id="deleted"> <label for="deleted">[% loc('Deleted') %]</label> </p> @@ -94,6 +96,11 @@ </p> <p> + <input type="checkbox" name="non_public" value="1" id="non_public"> + <label for="non_public">[% loc('Private') %]</label> + </p> + + <p> <input type="hidden" name="area_id" value="[% area_id %]" > <input type="hidden" name="posted" value="new" > <input type="hidden" name="token" value="[% token %]" > diff --git a/templates/web/default/admin/council_edit.html b/templates/web/default/admin/council_edit.html index 716c2cb08..408466b51 100644 --- a/templates/web/default/admin/council_edit.html +++ b/templates/web/default/admin/council_edit.html @@ -26,7 +26,8 @@ <strong>[% loc('Email:') %] </strong> <input type="text" name="email" value="[% contact.email | html %]" size="30"> <input type="checkbox" name="confirmed" value="1" id="confirmed"[% ' checked' IF contact.confirmed %]> <label for="confirmed">[% loc('Confirmed' ) %]</label> - <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> <label for="deleted">[% loc('Deleted') %]</label><br> + <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> <label for="deleted">[% loc('Deleted') %]</label> + <input type="checkbox" name="non_public" value="1" id="non_public"[% ' checked' IF contact.non_public %]> <label for="non_public">[% loc('Private') %]</label><br> <strong>[% loc('Note:') %] </strong><textarea name="note" rows="3" cols="40">[% contact.note | html %]</textarea> <br> diff --git a/templates/web/default/admin/index.html b/templates/web/default/admin/index.html index b1eddaa3a..2c5ee55db 100644 --- a/templates/web/default/admin/index.html +++ b/templates/web/default/admin/index.html @@ -21,7 +21,7 @@ [% IF c.cobrand.admin_show_creation_graph -%] <p> - <a href="[% c.config.BASE_URL %]/bci-live-creation.png">[% loc('Graph of problem creation by status over time') %]</a> + <a href="[% c.config.BASE_URL %]/fms-live-creation.png">[% loc('Graph of problem creation by status over time') %]</a> </p> [% END -%] diff --git a/templates/web/default/admin/report_edit.html b/templates/web/default/admin/report_edit.html index 9ef7e8248..d283037c2 100644 --- a/templates/web/default/admin/report_edit.html +++ b/templates/web/default/admin/report_edit.html @@ -40,6 +40,7 @@ <li>[% loc('Extra data:') %] [% problem.extra ? 'Yes' : 'No' %]</li> <li>[% loc('Going to send questionnaire?') %] [% IF problem.send_questionnaire %][% loc('Yes') %][% ELSE %][% loc('No') %][% END %]</li> <li><label for="flagged">[% loc('Flagged:') %]</label> <input type="checkbox" name="flagged"[% ' checked' IF problem.flagged %]></li> +<li><label for="non_public">[% loc('Private:') %]</label> <input type="checkbox" name="non_public"[% ' checked' IF problem.non_public %]></li> [% IF problem.photo %] [% photo = problem.get_photo_params %] diff --git a/templates/web/default/report/updates.html b/templates/web/default/report/updates.html index de873e2ed..eaf5209ff 100644 --- a/templates/web/default/report/updates.html +++ b/templates/web/default/report/updates.html @@ -23,7 +23,7 @@ [% tprintf( loc( 'Posted by %s at %s' ), update.name, prettify_epoch( update.confirmed_local.epoch ) ) | html -%] [%- END -%] [%- ", " _ loc( 'marked as fixed' ) IF update.mark_fixed %] - [%- ", " _ loc( 'reopened' ) IF update.mark_open %] - [%- ", " _ tprintf(loc( 'marked as %s' ), update.meta_problem_state) IF update.problem_state %] + [%- ", " _ loc( 'reopened' ) IF update.mark_open OR update.problem_state == 'confirmed' %] + [%- ", " _ tprintf(loc( 'marked as %s' ), update.meta_problem_state) IF update.problem_state AND update.problem_state != 'confirmed' %] [% END %] diff --git a/templates/web/default/reports/index.html b/templates/web/default/reports/index.html index 283df5285..76c2afcd2 100755 --- a/templates/web/default/reports/index.html +++ b/templates/web/default/reports/index.html @@ -34,6 +34,7 @@ <td class="data">[% fixed.${area.id}.new or 0 %]</td> <td class="data">[% fixed.${area.id}.old or 0 %]</td> </tr> +[% TRY %][% PROCESS "reports/_extras.html" %][% CATCH file %][% END %] [% END %] </tbody> </table> diff --git a/templates/web/fixmystreet/faq/faq-en-gb.html b/templates/web/fixmystreet/faq/faq-en-gb.html index bd94ecd38..9edb21426 100755 --- a/templates/web/fixmystreet/faq/faq-en-gb.html +++ b/templates/web/fixmystreet/faq/faq-en-gb.html @@ -18,6 +18,8 @@ or discuss local problems they’ve found to their local council by simply locating them on a map. It launched in early February 2007.</dd> + <dt>How do I get in touch with FixMyStreet?</dt> + <dd>Here’s our <a href="/contact">contact page</a>.</dd> <dt>What sort of problems should I report with FixMyStreet?</dt> <dd>FixMyStreet is primarily for reporting things which are <strong>broken or dirty or damaged or dumped, and need fixing, cleaning diff --git a/templates/web/fixmystreet/reports/_extras.html b/templates/web/fixmystreet/reports/_extras.html new file mode 100755 index 000000000..e210b9c07 --- /dev/null +++ b/templates/web/fixmystreet/reports/_extras.html @@ -0,0 +1,24 @@ +[% + fms_councils = { + 'Bromley Council' = 'fix.bromley.gov.uk' + 'Barnet Borough Council' = 'barnet.fixmystreet.com' + 'Lichfield District Council' = 'lichfielddc.fixmystreet.com' + 'Reading Borough Council' = 'reading.fixmystreet.com' + 'Southampton City Council' = 'southampton.fixmystreet.com' + } + secure = { + 'fix.bromley.gov.uk' = 's' + } + site = fms_councils.${area.name} +%] +[% IF site %] +<tr align="center" +[%- IF ! (loop.count % 2) %] class="a" +[%- END %]> +<td class="title" colspan="6" style="padding-top:0"> + <small title="This council's online reporting is powered by FixMyStreet">(includes reports from + <a href="http[% secure.$site %]://[% site %]">[% site %]</a> using + <a href="http://www.mysociety.org/for-councils/fixmystreet/">FixMyStreet for Councils</a>)</small> +</td> +</tr> +[% END %] diff --git a/templates/web/southampton/header.html b/templates/web/southampton/header.html index 43553468c..e02083a99 100644 --- a/templates/web/southampton/header.html +++ b/templates/web/southampton/header.html @@ -51,7 +51,6 @@ </form> </div> - <a class="mctv" href="http://www.southampton.mycounciltv.org"><img src="/cobrands/southampton/mctv.png" alt="Link to MyCouncilTV videos" /></a> <ul id="topNav"> <li><a href="http://www.southampton.gov.uk/online/">Do it online</a></li> <li><a href="http://www.southampton.gov.uk/customer-service/">Customer Services</a></li> diff --git a/web/.gitignore b/web/.gitignore index 124be032a..d6e2f1a1a 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1,4 +1,4 @@ /down.html /_Inline -/bci-live-creation.png -/bci-live-line.png +/fms-live-creation.png +/fms-live-line.png diff --git a/web/cobrands/fixmystreet/_base.scss b/web/cobrands/fixmystreet/_base.scss index 5d71c33e6..72c039075 100644 --- a/web/cobrands/fixmystreet/_base.scss +++ b/web/cobrands/fixmystreet/_base.scss @@ -1306,9 +1306,6 @@ table.nicetable { &.a { background:#f6f6f6; } - &:nth-child(even) { - background:#f6f6f6; - } &.gone { color: #666666; background-color: #cccccc; |