aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/ec2-rewrite-conf20
-rwxr-xr-xbin/install-as-user126
-rwxr-xr-xbin/open311-populate-service-list9
-rwxr-xr-xbin/pre-install-as-root307
-rwxr-xr-xbin/problem-creation-graph14
-rwxr-xr-xbin/problems-filed-graph6
m---------commonlib0
-rw-r--r--conf/apache-vhost.conf.example34
-rw-r--r--conf/crontab.example28
-rw-r--r--conf/httpd.conf-example40
-rw-r--r--conf/nginx.conf.example75
-rw-r--r--conf/packages.ubuntu-precise16
-rwxr-xr-xconf/sysvinit.example53
-rw-r--r--db/alert_types.sql18
-rw-r--r--db/generate_secret.sql8
-rw-r--r--db/migrate_from_osgb36_to_wgs84.pl10
-rw-r--r--db/schema.sql6
-rw-r--r--db/schema_0024-add_non_public_categories_and_problems.sql37
-rw-r--r--locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.mobin13250 -> 0 bytes
-rw-r--r--locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po124
-rw-r--r--notes/no-update-server2
-rw-r--r--perllib/CrossSell.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm7
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm7
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm9
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm11
-rw-r--r--perllib/FixMyStreet/App/Controller/Root.pm7
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm5
-rw-r--r--perllib/FixMyStreet/Cobrand/UK.pm4
-rw-r--r--perllib/FixMyStreet/DB/Result/Contact.pm6
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm6
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/AlertType.pm4
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Nearby.pm1
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm4
-rw-r--r--perllib/FixMyStreet/Geocode/OSM.pm4
-rw-r--r--perllib/FixMyStreet/TestMech.pm106
-rw-r--r--perllib/Open311.pm15
-rw-r--r--perllib/Utils.pm1
-rw-r--r--t/app/controller/admin.t347
-rw-r--r--t/app/controller/alert_new.t190
-rw-r--r--t/app/controller/around.t26
-rw-r--r--t/app/controller/index.t19
-rw-r--r--t/app/controller/report_display.t31
-rw-r--r--t/app/controller/report_new.t69
-rw-r--r--t/app/controller/report_updates.t45
-rw-r--r--t/app/controller/reports.t42
-rw-r--r--t/cobrand/closest.t2
-rw-r--r--t/open311.t37
-rw-r--r--templates/web/default/admin/council_contacts.html9
-rw-r--r--templates/web/default/admin/council_edit.html3
-rw-r--r--templates/web/default/admin/index.html2
-rw-r--r--templates/web/default/admin/report_edit.html1
-rw-r--r--templates/web/default/report/updates.html4
-rwxr-xr-xtemplates/web/default/reports/index.html1
-rwxr-xr-xtemplates/web/fixmystreet/faq/faq-en-gb.html2
-rwxr-xr-xtemplates/web/fixmystreet/reports/_extras.html24
-rw-r--r--templates/web/southampton/header.html1
-rw-r--r--web/.gitignore4
-rw-r--r--web/cobrands/fixmystreet/_base.scss3
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
deleted file mode 100644
index e09194c2b..000000000
--- a/locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.mo
+++ /dev/null
Binary files differ
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:&nbsp;%s"
-msgstr ""
+msgstr "%s ref:&nbsp;%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&rsquo;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&rsquo;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&rsquo;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&nbsp;:"
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&nbsp;:"
+"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&nbsp;:"
#: 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:&nbsp;%s"
-msgstr ""
+msgstr "deres ref:&nbsp;%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&rsquo;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&rsquo;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;