diff options
33 files changed, 1486 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore index 27d7ced66..05d2b275f 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ FixMyBarangay.po /web/cobrands/fixmystreet/*.css /web/cobrands/bromley/*.css /web/cobrands/fixmybarangay/*.css +/web/cobrands/oxfordshire/*.css /web/cobrands/stevenage/*.css /web/cobrands/barnet/*.css /web/cobrands/zurich/*.css diff --git a/bin/make_css b/bin/make_css index a86fd4f0d..cd78e7f13 100755 --- a/bin/make_css +++ b/bin/make_css @@ -14,7 +14,7 @@ DIRECTORY=$(cd `dirname $0`/../web && pwd) # FixMyStreet uses compass -NEWSTYLE=${1:-"fixmystreet bromley fixmybarangay barnet zurich default stevenage"} +NEWSTYLE=${1:-"fixmystreet bromley fixmybarangay barnet zurich default stevenage oxfordshire"} NEWSTYLE_REGEX=${NEWSTYLE// /\\|} for site in $NEWSTYLE; do compass compile --output-style compressed $DIRECTORY/cobrands/$site diff --git a/bin/oxfordshire/open311_service_request.cgi b/bin/oxfordshire/open311_service_request.cgi new file mode 100755 index 000000000..109981fda --- /dev/null +++ b/bin/oxfordshire/open311_service_request.cgi @@ -0,0 +1,562 @@ +#!/usr/bin/perl + +# script for absobring incoming Open311 service request POSTs and +# passing them into Bentley EXOR backend via create_enquiry stored +# procedure. +# +# mySociety: http://code.fixmystreet.com/ +#----------------------------------------------------------------- + +use strict; +use CGI; +use DBI; +use DBD::Oracle qw(:ora_types); +use Time::Piece; + +################################################################### +# Config file: values in the config file override any values set +# in the code below for the following things: +# +# host: SXX-SAN-FOO_BAR +# sid: FOOBAR +# port: 1531 +# username: foo +# password: FooBar +# testing: 0 +# +# Absence of the config file fails silently in case you really are +# using values directly set in this script. +#------------------------------------------------------------------ +my $CONFIG_FILENAME = "/usr/local/etc/fixmystreet.config"; + + +use constant { + GENERAL_SERVICE_ERROR => 400, + CODE_OR_ID_NOT_FOUND => 404, + CODE_OR_ID_NOT_PROVIDED => 400, + BAD_METHOD => 405, + FATAL_ERROR => 500 +}; + +my $DB_SERVER_NAME = 'FOO'; +my $DB_HOST = $DB_SERVER_NAME; # did this just in case we need to add more to the name (e.g, domain) +my $DB_PORT = '1531'; +my $ORACLE_SID = 'FOOBAR'; +my $USERNAME = 'FIXMYSTREET'; +my $PASSWORD = 'XXX'; +my $STORED_PROC_NAME = 'PEM.create_enquiry'; + +# NB can override this setting in the config file! +# 'ruthless' removes everything (i.e. all POSIX control chars) +# 'desc' removes everything, but keeps tabs and newlines in the 'description' field, where they matter +# 'normal' keeps tabs and newlines +my $STRIP_CONTROL_CHARS = 'normal'; + +my $TESTING_WRITE_TO_FILE = 0; # write to file instead of DB +my $OUT_FILENAME = "fms-test.txt"; +my $TEST_SERVICE_DISCOVERY=0; # switch to 1 to run service discovery, which confirms the DB connection at least + +my %PEM_BOUND_VAR_TYPES; +my @PEM_BOUND_VAR_NAMES; +foreach (get_pem_field_names()) { + if (s/__(NUMBER|DATE)$//) { + push @PEM_BOUND_VAR_NAMES, $_; + $PEM_BOUND_VAR_TYPES{$_} = $1 || ''; # empty for varchar2 + } else { + push @PEM_BOUND_VAR_NAMES, $_; + } +} + +# Config file overrides existing values for these, if present: +if ($CONFIG_FILENAME && open(CONF, $CONFIG_FILENAME)) { + while (<CONF>) { + next if /^#/; + if (/^\s*password:\s*(\S+)\s*$/i) { + $PASSWORD = $1; + } elsif (/^\s*sid:\s*(\S+)\s*$/i) { + $ORACLE_SID = $1; + } elsif (/^\s*username:\s*(\S+)\s*$/i) { + $USERNAME = $1; + } elsif (/^\s*port:\s*(\S+)\s*$/i) { + $DB_PORT = $1; + } elsif (/^\s*host:\s*(\S+)\s*$/i) { + $DB_HOST = $1; + } elsif (/^\s*testing:\s*(\S+)\s*$/i) { + $TESTING_WRITE_TO_FILE = $1; + } elsif (/^\s*test-service-discovery:\s*(\S+)\s*$/i) { + $TEST_SERVICE_DISCOVERY = $1; + } elsif (/^\s*strip-control-chars:\s*(\S+)\s*$/i) { + $STRIP_CONTROL_CHARS = lc $1; + } + } +} + +# assuming Oracle environment is happily set already, don't need these: +# my $ORACLE_HOME = "/app/oracle/product/11.2.0/db_1"; +# $ENV{ORACLE_HOME} = $ORACLE_HOME; +# $ENV{ORACLE_SID} = $ORACLE_SID; +# $ENV{PATH} ="$ORACLE_HOME/bin"; +# $ENV{LD_LIBRARY_PATH}="$ORACLE_HOME/lib"; + +my $ERR_MSG = 'error'; # unique key in data hash + +# incoming (Open311, from FMS) field names +my %F = ( + 'ACCOUNT_ID' => 'account_id', + 'ADDRESS_ID' => 'address_id', + 'ADDRESS_STRING' => 'address_string', + 'API_KEY' => 'api_key', + 'DESCRIPTION' => 'description', + 'DEVICE_ID' => 'device_id', + 'EASTING' => 'attribute[easting]', + 'EMAIL' => 'email', + 'FIRST_NAME' => 'first_name', + 'FMS_ID' => 'attribute[external_id]', + 'LAST_NAME' => 'last_name', + 'LAT' => 'lat', + 'LONG' => 'long', + 'MEDIA_URL' => 'media_url', + 'NORTHING' => 'attribute[northing]', + 'PHONE' => 'phone', + 'REQUESTED_DATETIME' => 'requested_datetime', + 'SERVICE_CODE' => 'service_code', + 'STATUS' => 'status', +); + +my $req = new CGI; + +# normally, POST requests are inserting service requests +# and GET requests are for returning service requests, although OCC aren't planning on +# using that (it's part of the Open311 spec). +# So actually the service discovery is more useful, so send in a 'services' param +# to see that. +# +# But for testing the db connection, set $TEST_SERVICE_DISCOVERY so that +# *all* requests simply do a service discovery by setting (possibly via the config file) + +if ($TEST_SERVICE_DISCOVERY) { + get_service_discovery($req); # to test +}elsif ($ENV{'REQUEST_METHOD'} eq "POST") { + post_service_request($req); +} elsif ($req -> param('services')) { + get_service_discovery($req); +} else { + ### # allow a GET to make an insert, for testing (from the commandnd line!) + ### my $fixme = get_FAKE_INSERT($req); print "Returned $fixme\n"; + get_service_requests($req); +} + +#---------------------------------------------------- +# post_service_request +# accepts an incoming service request +# If everything goes well, it puts it in the database and +# returns the PEM ID to the caller +#---------------------------------------------------- +sub post_service_request { + my $req = shift; + my %data; + my $pem_id = 0; + + foreach (values %F) { + $data{$_} = $req -> param($_); + $data{$_} =~ s/^\s+|\s+$//g; # trim + + if ($STRIP_CONTROL_CHARS) { + if ($STRIP_CONTROL_CHARS eq 'ruthless') { + $data{$_} =~ s/[[:cntrl:]]/ /g; # strip all control chars, simples + } elsif ($STRIP_CONTROL_CHARS eq 'desc') { + if ($_ eq 'DESCRIPTION') { + $data{$_} =~ s/[^\t\n[:^cntrl:]]/ /g; # leave tabs and newlines + } else { + $data{$_} =~ s/[[:cntrl:]]/ /g; # strip all control chars, simples + } + } else { + $data{$_} =~ s/[^\t\n[:^cntrl:]]/ /g; # leave tabs and newlines + } + } + } + + error_and_exit(CODE_OR_ID_NOT_PROVIDED, "missing service code (Open311 requires one)") + unless $data{$F{SERVICE_CODE}}; + error_and_exit(GENERAL_SERVICE_ERROR, "the service code you provided ($data{$F{SERVICE_CODE}}) was not recognised by this server") + unless service_exists($data{$F{SERVICE_CODE}}); + error_and_exit(GENERAL_SERVICE_ERROR, "no address or long-lat provided") + unless ( (is_longlat($data{$F{LONG}}) && is_longlat($data{$F{LAT}})) || $data{$F{ADDRESS_STRING}} ); + + if ($TESTING_WRITE_TO_FILE) { + $pem_id = dump_to_file(\%data); + } else { + $pem_id = insert_into_pem(\%data); + } + + if (! $pem_id) { + error_and_exit(FATAL_ERROR, $data{$ERR_MSG} || "failed to get PEM ID"); + } else { + print <<XML; +Content-type: text/xml + +<?xml version="1.0" encoding="utf-8"?> +<service_requests> + <request> + <service_request_id>$pem_id</service_request_id> + </request> +</service_requests> +XML + } +} + +#------------------------------------------------------------------ +# error_and_exit +# args: HTTP status code, error message +# Sends out the HTTP status code and message +# and temrinates execution +#------------------------------------------------------------------ +sub error_and_exit { + my ($status, $msg) = @_; + print "Status: $status $msg\n\n$msg\n"; + exit; +} + +#------------------------------------------------------------------ +# is_longlat +# returns true if this looks like a long/lat value +#------------------------------------------------------------------ +sub is_longlat { + return $_[0] =~ /^-?\d+\.\d+$/o? 1 : 0; +} + +#------------------------------------------------------------------ +# get_db_connection +# no args: uses globals, possibly read from config +# returns handle for the connection (otherwise terminates) +#------------------------------------------------------------------ +sub get_db_connection { + return DBI->connect( "dbi:Oracle:host=$DB_HOST;sid=$ORACLE_SID;port=$DB_PORT", $USERNAME, $PASSWORD ) + or error_and_exit(FATAL_ERROR, "failed to connect to database: " . $DBI::errstr, ""); +} + +#------------------------------------------------------------------ +# service_exists +# lookup the service code, to check that it exists +# SELECT det_code, det_name FROM higatlas.doc_enquiry_types WHERE +# det_dtp_code = 'REQS' AND det_dcl_code ='SERV' AND det_con_id=1 +# Actually, FMS is expected to be sending good codes because they +# come from here anyway, and are expected to be stable. But could +# cache and check... probably overkill since DB insert will probably +# throw the error anyway. +#------------------------------------------------------------------ +sub service_exists { + my $service_code = shift; + return 1; +} + +#------------------------------------------------------------------ +# dump_to_file +# args: ref to hash of data +# for testing, log the incoming data into a local file +# NB throws a fatal error +#------------------------------------------------------------------ +sub dump_to_file { + my $h = shift; # href to data hash + if (open (OUTFILE, ">$OUT_FILENAME")) { + print OUTFILE "Data dump: " . gmtime() . "\n" . '-' x 64 . "\n\n"; + foreach (sort keys %$h) { + print OUTFILE "$_ => " . $$h{$_} . "\n"; + } + print OUTFILE "\n\n" . '-' x 64 . "\n[end]\n"; + close OUTFILE; + $$h{$ERR_MSG} = "NB did not write to DB (see $OUT_FILENAME instead: switch off \$TESTING_WRITE_TO_FILE to stop this)"; + } else { + $$h{$ERR_MSG} = "failed to write to outfile ($!)"; + } + return 0; # test always throws an error so no risk of production confusion! +} + +#------------------------------------------------------------------ +# insert_into_pem +# args: hashref to data hash +# returns PEM id of the new record (or passes an error message +# into the data hash if no id is available) +#------------------------------------------------------------------ +sub insert_into_pem { + my $h = shift; # href to data hash + + my $dbh = get_db_connection(); + + my $pem_id; + my $error_value; + my $error_product; + + # set specifc vars up where further processing on them might be needed: + my $undef = undef; + my $address = $$h{$F{ADDRESS_STRING}}; + my $status = $$h{$F{STATUS}}; + my $service_code = $$h{$F{SERVICE_CODE}}; + my $description = $$h{$F{DESCRIPTION}}; + my $media_url = $$h{$F{MEDIA_URL}}; + if ($media_url) { + $description .= ($STRIP_CONTROL_CHARS ne 'ruthless'? "\n\n":" ") . "Photo: $media_url"; + } + + my $sth = $dbh->prepare(q# + BEGIN + PEM.create_enquiry( + ce_cat => :ce_cat, + ce_class => :ce_class, + ce_forename => :ce_forename, + ce_surname => :ce_surname, + ce_contact_type => :ce_contact_type, + ce_work_phone => :ce_work_phone, + ce_email => :ce_email, + ce_description => :ce_description, + ce_enquiry_type => :ce_enquiry_type, + ce_source => :ce_source, + ce_incident_datetime => to_Date(:ce_incident_datetime,'YYYY-MM-DD HH24:MI'), + ce_x => :ce_x, + ce_y => :ce_y, + ce_doc_reference => :ce_doc_reference, + ce_status_code => :ce_status_code, + ce_compl_user_type => :ce_compl_user_type, + error_value => :error_value, + error_product => :error_product, + ce_doc_id => :ce_doc_id); + END; +#); + + my %bindings; + # comments here are suggested values + # fixed values + $bindings{":ce_cat"} = 'REQS'; # or REQS ? + $bindings{":ce_class"} = 'SERV'; # 'FRML' ? + $bindings{":ce_contact_type"} = 'ENQUIRER'; # 'ENQUIRER' + $bindings{":ce_status_code"} = 'RE'; # RE=received (?) + $bindings{":ce_compl_user_type"}= 'USER'; # 'USER' + + # ce_incident_datetime is *not* an optional param, but FMS isn't sending it at the moment + $bindings{":ce_incident_datetime"}=$$h{$F{REQUESTED_DATETIME}} || Time::Piece->new->strftime('%Y-%m-%d %H:%M'); + + # especially FMS-specific: + $bindings{":ce_source"} = "FMS"; # important, and specific to this script! + $bindings{":ce_doc_reference"} = $$h{$F{FMS_ID}}; # FMS id + $bindings{":ce_enquiry_type"} = $service_code; + + # incoming data + $bindings{":ce_x"} = $$h{$F{EASTING}}; + $bindings{":ce_y"} = $$h{$F{NORTHING}}; + $bindings{":ce_forename"} = substr($$h{$F{FIRST_NAME}}, 0, 30); # 'CLIFF' + $bindings{":ce_surname"} = substr($$h{$F{LAST_NAME}}, 0, 30); # 'STEWART' + $bindings{":ce_work_phone"} = substr($$h{$F{PHONE}}, 0, 25); # '0117 600 4200' + $bindings{":ce_email"} = substr($$h{$F{EMAIL}}, 0, 50); # 'info@exor.co.uk' + $bindings{":ce_description"} = substr($description, 0, 2000); # 'Large Pothole' + + foreach my $name (sort keys %bindings) { + next if grep {$name eq $_} (':error_value', ':error_product', ':ce_doc_id'); # return values + my $type = $PEM_BOUND_VAR_TYPES{$name} || 'VARCHAR2'; + $sth->bind_param( + $name, + $bindings{$name}, + $type eq 'NUMBER'? ORA_NUMBER : ($type eq 'DATE'? ORA_DATE : ORA_VARCHAR2 ) + ); + } + + # not used, but from the example docs, for reference + # $sth->bind_param(":ce_contact_title", $undef); # 'MR' + # $sth->bind_param(":ce_postcode", $undef); # 'BS11EJ' NB no spaces, upper case + # $sth->bind_param(":ce_building_no", $undef); # '1' + # $sth->bind_param(":ce_building_name", $undef); # 'CLIFTON HEIGHTS' + # $sth->bind_param(":ce_street", $undef); # 'HIGH STREET' + # $sth->bind_param(":ce_town", $undef); # 'BRSITOL' + # $sth->bind_param(":ce_location", $undef); # 'Outside Flying Horse Public House' + # $sth->bind_param(":ce_enquiry_type", $undef); # 'CD' , ce_source => 'T' + # $sth->bind_param(":ce_cpr_id", $undef); # '5' (priority) + # $sth->bind_param(":ce_rse_he_id", $undef); #> nm3net.get_ne_id('1200D90970/09001','L') + # $sth->bind_param(":ce_compl_target", $undef); # '08-JAN-2004' + # $sth->bind_param(":ce_compl_corresp_date",$undef); # '02-JAN-2004' + # $sth->bind_param(":ce_compl_corresp_deliv_date", $undef); # '02-JAN-2004' + # $sth->bind_param(":ce_resp_of", $undef); # 'GBOWLER' + # $sth->bind_param(":ce_hct_vip", $undef); # 'CO' + # $sth->bind_param(":ce_hct_home_phone", $undef); # '0117 900 6201' + # $sth->bind_param(":ce_hct_mobile_phone", $undef); # '07111 1111111' + # $sth->bind_param(":ce_compl_remarks", $undef); # remarks (notes) max 254 char + + # return values: + $sth->bind_param_inout(":error_value", \$error_value, 12); #> l_ERROR_VALUE # number + $sth->bind_param_inout(":error_product", \$error_product, 10); #> l_ERROR_PRODUCT (will always be 'DOC') + $sth->bind_param_inout(":ce_doc_id", \$pem_id, 12); #> l_ce_doc_id # number + + $sth->execute(); + $dbh->disconnect; + + # if error, maybe need to look it up: + # error_value is the index HER_NO in table HIG_ERRORS, which has messages + # actually err_product not helpful (wil always be "DOC") + $$h{$ERR_MSG} = "$error_value $error_product" if ($error_value || $error_product); + + return $pem_id; +} + +#------------------------------------------------------------------ +# get_service_requests +# Strictly speaking, Open311 would expect the GET request for service +# requests to respond with all service requests (within a specified +# period). But as we're not using that, do a service discovery +# instead. +#------------------------------------------------------------------ +sub get_service_requests { + # error_and_exit(BAD_METHOD, "sorry, currently only handling incoming Open311 service requests: use POST method"); + get_service_discovery(); # for now +} + +#------------------------------------------------------------------ +# get_FAKE_INSERT +# for testing off command line, force the data +#------------------------------------------------------------------ +sub get_FAKE_INSERT { + my %fake_data = ( + $F{'DESCRIPTION'} => 'Testing, description', + $F{'EASTING'} => '45119', + $F{'EMAIL'} => 'email@example.com', + $F{'FIRST_NAME'} => 'Dave', + $F{'FMS_ID'} => '1012', + $F{'LAST_NAME'} => 'Test', + $F{'LAT'} => '51.756741605999', + $F{'LONG'} => '-1.2596387532192', + $F{'NORTHING'} => '206709', + $F{'SERVICE_CODE'} => 'OT', + $F{'MEDIA_URL'} => 'http://www.example.com/pothole.jpg', + ); + return insert_into_pem(\%fake_data) +} + +#------------------------------------------------------------------ +# get_service_discovery +# Although not really implementing this, use it as a test to read the +# db and confirm connectivity. +#------------------------------------------------------------------ +sub get_service_discovery { + my $dbh = get_db_connection(); + my $ary_ref = $dbh->selectall_arrayref(qq(select det_code, det_name from higatlas.doc_enquiry_types where det_dtp_code = 'REQS' AND det_dcl_code='SERV' and det_con_id=1)); + # rough and ready XML dump now (should use XML Simple to build/escape properly!) + my $xml = ""; + foreach my $row(@{$ary_ref}) { + if (defined $row) { + my ($code, $name) = @$row; + $xml.= <<XML; + <service> + <service_code>$code</service_code> + <metadata>false</metadata> + <type>realtime</type> + <keywords/> + <group/> + <service_name>$name</service_name> + <description/> + </service> +XML + } + } + print <<XML; +Content-type: text/xml + +<?xml version="1.0" encoding="utf-8"?> +<services> +$xml +</services> +XML +} + +#------------------------------------------------------------------ +# get_pem_field_names +# return list of params for the stored procedure *in the correct order* +# Also: __NUMBER and __DATE suffixes for anything that isn't a VARCHAR2 +# This also adds the colon prefix to all names. +# Note the last three of these are inout params, and are handled +# as a special (hardcoded) case when used (see above). +# +# These are currently only used for type lookup, so should probably +# move them into the code as a name => type lookup; furthermore most of +# these are not used, and default to varchar2 anyway. +#------------------------------------------------------------------ +sub get_pem_field_names { + return map {":$_"} qw( +ce_cat +ce_class +ce_title +ce_contact_title +ce_forename +ce_surname +ce_contact_type +ce_flag +ce_pcode_id +ce_postcode +ce_building_no +ce_building_name +ce_street +ce_locality +ce_town +ce_county +ce_organisation +ce_work_phone +ce_email +ce_location +ce_description +ce_enquiry_type +ce_source +ce_incident_datetime__DATE +ce_cpr_id +ce_asset_id +ce_rse_he_id +ce_x__NUMBER +ce_y__NUMBER +ce_date_expires__DATE +ce_doc_reference +ce_issue_number__NUMBER +ce_category +ce_status_date__DATE +ce_resp_of +ce_compl_ack_flag +ce_compl_ack_date__DATE +ce_compl_flag +ce_compl_peo_date__DATE +ce_compl_target__DATE +ce_compl_complete__DATE +ce_compl_referred_to +ce_compl_police_notif_flag +ce_compl_date_police_notif +ce_compl_from__DATE +ce_compl_to__DATE +ce_compl_claim +ce_compl_corresp_date__DATE +ce_compl_corresp_deliv_date__DATE +ce_compl_no_of_petitioners__NUMBER +ce_compl_remarks +ce_compl_cause +ce_compl_injuries +ce_compl_damgae +ce_compl_action +ce_compl_litigation_flag +ce_compl_litigation_reason +ce_compl_claim_no +ce_compl_determination +ce_compl_est_cost__NUMBER +ce_compl_adv_cost__NUMBER +ce_compl_act_cost__NUMBER +ce_compl_follow_up1__DATE +ce_compl_follow_up2__DATE +ce_compl_follow_uo3__DATE +ce_compl_insurance_claim +ce_compl_summons_received +ce_compl_user_type +ce_hct_vip +ce_hct_home_phone +ce_hct_mobile_phone +ce_hct_fax +ce_had_sub_build_name +ce_had_property_type +ce_status_code +ce_date_time_arrived__DATE +ce_reason_late +error_value__NUMBER +error_product +ce_doc_id__NUMBER + ) +} diff --git a/conf/crontab.ugly b/conf/crontab.ugly index a88e774d2..95ca4b38d 100644 --- a/conf/crontab.ugly +++ b/conf/crontab.ugly @@ -20,7 +20,7 @@ MAILTO=!!(*= $user *)!!@mysociety.org #2 * * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-alerts.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-alerts" || echo "stalled?" 0,30 * * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-questionnaires.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-questionnaires" || echo "stalled?" -!!(* } elsif (($vhost eq 'www.fixmystreet.com') || ($vhost eq 'bromley.test.mysociety.org') || ($vhost eq 'barnet.fixmystreet.staging.mysociety.org') || ($vhost eq 'fixmybarangay.test.mysociety.org') || ($vhost eq 'demo.fixmybarangay.com') || ($vhost eq 'www.fixmybarangay.com') || ($vhost eq 'stevenage.test.mysociety.org')) { *)!! +!!(* } elsif (($vhost eq 'www.fixmystreet.com') || ($vhost eq 'bromley.test.mysociety.org') || ($vhost eq 'barnet.fixmystreet.staging.mysociety.org') || ($vhost eq 'oxfordshire.fixmystreet.staging.mysociety.org') || ($vhost eq 'demo.fixmybarangay.com') || ($vhost eq 'www.fixmybarangay.com') || ($vhost eq 'stevenage.test.mysociety.org')) { *)!! 5,10,15,20,25,30,35,40,45,50,55 * * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-reports.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-reports" || echo "stalled?" 0 0-7,9-11,13-15,17-23 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-reports.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-reports" || echo "stalled?" 0 8,12,16 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-reports.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-reports --verbose" || echo "stalled?" diff --git a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm new file mode 100644 index 000000000..578dfa53c --- /dev/null +++ b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm @@ -0,0 +1,63 @@ +package FixMyStreet::Cobrand::Oxfordshire; +use base 'FixMyStreet::Cobrand::UKCouncils'; + +use strict; +use warnings; + +sub council_id { return 2237; } +sub council_area { return 'Oxfordshire'; } +sub council_name { return 'Oxfordshire County Council'; } +sub council_url { return 'oxfordshire'; } + +sub base_url { + return FixMyStreet->config('BASE_URL') if FixMyStreet->config('STAGING_SITE'); + return 'http://fixmystreet.oxfordshire.gov.uk'; +} + +# Different to councils parent due to this being a two-tier council. If we get +# more, this can be genericised in the parent. +sub problems_clause { + return { council => { like => '%2237%' } }; +} + +sub path_to_web_templates { + my $self = shift; + return [ + FixMyStreet->path_to( 'templates/web', $self->moniker )->stringify, + FixMyStreet->path_to( 'templates/web/fixmystreet' )->stringify + ]; +} + +sub enter_postcode_text { + my ($self) = @_; + return 'Enter an Oxfordshire postcode, or street name and area'; +} + +sub disambiguate_location { + my $self = shift; + my $string = shift; + return { + %{ $self->SUPER::disambiguate_location() }, + centre => '51.765765,-1.322324', + span => '0.154963,0.24347', # NB span is not correct + bounds => [ 51.459413, -1.719500, 52.168471, -0.870066 ], + }; +} + +sub example_places { + return ( 'OX20 1SZ', 'Park St, Woodstock' ); +} + +# If we ever link to a district problem report, needs to be to main FixMyStreet +sub base_url_for_report { + my ( $self, $report ) = @_; + my %councils = map { $_ => 1 } @{$report->councils}; + if ( $councils{2237} ) { + return $self->base_url; + } else { + return FixMyStreet->config('BASE_URL'); + } +} + +1; + diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index ce197076b..feca81d43 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -581,7 +581,8 @@ sub body { # Note: this only makes sense when called on a problem that has been sent! sub can_display_external_id { my $self = shift; - if ($self->external_id && $self->send_method_used && $self->send_method_used eq 'barnet') { + if ($self->external_id && $self->send_method_used && + ($self->send_method_used eq 'barnet' || $self->cobrand eq 'oxfordshire')) { return 1; } return 0; diff --git a/perllib/FixMyStreet/SendReport/Open311.pm b/perllib/FixMyStreet/SendReport/Open311.pm index 8d7a418af..27b65137e 100644 --- a/perllib/FixMyStreet/SendReport/Open311.pm +++ b/perllib/FixMyStreet/SendReport/Open311.pm @@ -9,6 +9,9 @@ use FixMyStreet::App; use mySociety::Config; use DateTime::Format::W3CDTF; use Open311; +use Readonly; + +Readonly::Scalar my $COUNCIL_ID_OXFORDSHIRE => 2237; sub should_skip { my $self = shift; @@ -67,6 +70,17 @@ sub send { $basic_desc = 1; } + # extra Oxfordshire fields: send northing and easting, and the FMS id + if ( $row->council =~ /$COUNCIL_ID_OXFORDSHIRE/ ) { + my $extra = $row->extra; + push @$extra, { name => 'external_id', value => $row->id }; + if ( $row->used_map || ( !$row->used_map && !$row->postcode ) ) { + push @$extra, { name => 'northing', value => $h->{northing} }; + push @$extra, { name => 'easting', value => $h->{easting} }; + } + $row->extra( $extra ); + } + # FIXME: we've already looked this up before my $contact = FixMyStreet::App->model("DB::Contact")->find( { deleted => 0, @@ -89,20 +103,25 @@ sub send { $open311->endpoints( { services => 'Services', requests => 'Requests' } ); } + # non-standard Oxfordshire endpoint (because it's just a script, not a full Open311 service) + if ( $row->council =~ /$COUNCIL_ID_OXFORDSHIRE/ ) { + $open311->endpoints( { requests => 'open311_service_request.cgi' } ); + } + # required to get round issues with CRM constraints if ( $row->council =~ /2218/ ) { $row->user->name( $row->user->id . ' ' . $row->user->name ); } if ($row->cobrand eq 'fixmybarangay') { - # FixMyBarangay endpoints expect external_id as an attribute + # FixMyBarangay endpoints expect external_id as an attribute, as do Oxfordshire $row->extra( [ { 'name' => 'external_id', 'value' => $row->id } ] ); } my $resp = $open311->send_service_request( $row, $h, $contact->email ); # make sure we don't save user changes from above - if ( $row->council =~ /2218/ || $row->council =~ /2482/ || $row->cobrand eq 'fixmybarangay') { + if ( $row->council =~ /(2218|2482|$COUNCIL_ID_OXFORDSHIRE)/ || $row->cobrand eq 'fixmybarangay') { $row->discard_changes(); } diff --git a/templates/web/oxfordshire/around/intro.html b/templates/web/oxfordshire/around/intro.html new file mode 100644 index 000000000..81b2569f6 --- /dev/null +++ b/templates/web/oxfordshire/around/intro.html @@ -0,0 +1 @@ + <h1 class="main">Reporting a problem in Oxfordshire</h1> diff --git a/templates/web/oxfordshire/faq/faq-en-gb.html b/templates/web/oxfordshire/faq/faq-en-gb.html new file mode 100755 index 000000000..02dd23cd9 --- /dev/null +++ b/templates/web/oxfordshire/faq/faq-en-gb.html @@ -0,0 +1,206 @@ +[% INCLUDE 'header.html', title => loc('Frequently Asked Questions'), bodyclass => 'twothirdswidthpage' %] + +<div class="sticky-sidebar"> + <aside> + <ul class="plain-list"> + <li><a href="#faq">Frequently Asked Questions</a></li> + <li><a href="#practical">Practical Questions</a></li> + <li><a href="#organisation">Organisation Questions</a></li> + <li><a href="/privacy">Privacy and cookies</a></li> + <li><a href="/contact">Contact FixMyStreet</a></li> + </ul> + </aside> +</div> + +<h1><a name="faq"></a>Frequently Asked Questions</h1> + <dl> + <dt>What is FixMyStreet?</dt> + <dd>FixMyStreet is a site to help people report, view, +or discuss local problems they’ve found to their local council by +simply locating them on a map. It launched in early February +2007.</dd> + + <dt>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 +or clearing</strong>, such as: + + <ul><li>Abandoned vehicles + <li>Dog Fouling + <li>Flyposting or graffiti + <li>Flytipping or litter + <li>Streetcleaning, such as broken glass in a cycle lane + <li>Unlit lamposts + <li>Potholes + </ul> + </dd> + + <dt>What isn’t FixMyStreet for?</dt> + <dd>FixMyStreet is not a way of getting in touch with the council for all + issues – please use FixMyStreet only for problems such as the above. We + often route problem reports via cleansing services or highways and so using + FixMyStreet for other matters may result in a delay in your report getting + to the right department. <strong>You will need to contact the council + directly for problems such as</strong>: + + <ul><li>Anti-social behaviour + <li>Any urgent or emergency problems + <li>Noise pollution or barking dogs + <li>Fires and smoke/smell pollution + <li>Missing wheelie bins or recycling boxes or missed rubbish collections + <li>Proposals for speed bumps/ CCTV/ pedestrian crossings/ new road layouts/ etc. + <li>Complaining about your neighbours + <li>Complaining about the council + <li>Joy riding, drug taking, animal cruelty, or other criminal activity + </ul> + <p>Councils often have direct hotlines for these sorts of issues.</p> + </dd> + + <dt><a name="pothole"></a>Should I report a pothole on this site, or call?</dt> +<dd> +<p>Please use the following chart to determine the size of any pot holes being +reported and whether to submit a report online or by telephone.</p> + +<ul> +<li>Depth of a milk bottle, <em>or</em> size of a dustbin lid? <strong>Call</strong>. +<li>Depth of a golf/ping pong ball? <strong>Report online</strong> +<li>Depth of a tennis ball, size of a dinner plate, <em>and</em> on a busy carriageway? <strong>Call</strong> +<li>Depth of a tennis ball, otherwise? <strong>Report online</strong> +<li>Depth of a coke can, on a pathway or busy carriageway? <strong>Call</strong> +<li>Depth of a coke can, size of a dinner plate, on a quiet carriageway? <strong>Call</strong> +<li>Depth of a coke can, otherwise? <strong>Report online</strong> +</ul> + +</dd> + + <dt>How do I use the site?</dt> + <dd>After entering a postcode or location, you are presented +with a map of that area. You can view problems already reported in that area, +or report ones of your own simply by clicking on the map at the location of +the problem.</dd> + + <dt>How are the problems solved?</dt> + <dd>They are reported to the council by email. The +council can then resolve the problem the way they normally would. +Alternatively, you can discuss the problem on the website with others, and +then together lobby the council to fix it, or fix it directly yourselves.</dd> + + <dt>Is it free?</dt> + <dd>The site is free to use, yes. FixMyStreet is run +by a registered charity, though, so if you want to make a contribution, <a +href="https://secure.mysociety.org/donate/">please do</a>.</dd> + + <dt>Can I use FixMyStreet on my mobile?</dt> + <dd> + <p>The FixMyStreet website should work on your mobile phone, adapting to + the size of your screen automatically. We plan to release updated native + apps in the near future. + <ul> + <li><em>iPhone:</em> Our basic app from 2008 is available for download + on the App Store: + <a href="http://itunes.apple.com/gb/app/fixmystreet/id297456545">FixMyStreet</a>, + <li><em>Android:</em> A volunteer, Anna Powell-Smith, has written an app + available from the + <a href="https://market.android.com/details?id=com.android.fixmystreet">Android Market</a>. + <li><em>Nokia:</em> A volunteer, Thomas Forth, has written an app available from the + <a href="http://store.ovi.com/content/107557">Ovi Store</a>. + </ul> + </dd> + + </dl> + + <h2><a name="practical"></a>Practical Questions</h2> + <dl> + <dt>Do you remove silly or illegal content?</dt> + <dd>FixMyStreet is not responsible for the content and accuracy +of material submitted by its users. We reserve the right to edit or remove any +problems or updates which we consider to be inappropriate upon being informed +by a user of the site.</dd> + + <dt>Why does the site use kilometres for measurements?</dt> + <dd>Thanks for asking politely – we never quite understand why some of the rudest + emails we receive are on this topic. The British national + grid reference system, devised by Ordnance Survey (the British national + mapping agency) around the time of the second world war, uses eastings and + northings measured in metres and kilometres; the maps we use are from + Ordnance Survey and so this is what we use to display distances. + There you have it: not everything British is in miles!</dd> + + <dt>Why can’t I zoom out more on the reporting map?</dt> + <dd>We want to keep FixMyStreet locally focused, so restrict the ability to + move radically between areas. The map on Your Reports will let you see all + the reports you’ve made, wherever they are. If you’re from the + council then the emailed version of the problem report also contains the + closest road and postcode to the pin on the map.</dd> + + <dt>This site is great – why aren’t you better publicised?</dt> + <dd>As a tiny charity we simply don’t have a publicity budget, and we + rely on word of mouth to advertise the site. We have a whole <a + href="posters/">array of posters, flyers and badges</a> if you’d like + to publicise us on the web or in your local area, and why not write to your + local paper to let them know about us?</dd> </dl> + + <h2><a name="organisation"></a>Organisation Questions</h2> + <dl> + <dt>Who built FixMyStreet?</dt> + <dd>This site was built by <a href="http://www.mysociety.org/">mySociety</a>, + in conjunction with the <a href="http://www.youngfoundation.org.uk/">Young Foundation</a>. +mySociety is the project of a registered charity which has grown out of the community of +volunteers who built sites like <a href="http://www.theyworkforyou.com/">TheyWorkForYou.com</a>. +mySociety’s primary mission is to build Internet projects which give people simple, tangible +benefits in the civic and community aspects of their lives. Our first project +was <a href="http://www.writetothem.com/">WriteToThem</a>, where you can write to any of your +elected representatives, for free. The charity is called UK Citizens Online Democracy and is charity number 1076346. mySociety +can be contacted by email at <a href="mailto:hello@mysociety.org">hello@mysociety.org</a>, +or by post at mySociety, 483 Green Lanes, London, N13 4BS, UK.</dd> + <dt><img src="/i/moj.png" align="right" alt="Ministry of Justice" hspace="10">Who pays for it?</dt> + <dd>FixMyStreet was originally paid for via the Department for + Constitutional Affairs Innovations Fund. It is now funded by a variety of means, from commercial + work to <a href="http://www.mysociety.org/donate/">donations</a>.</dd> + <dt><a name="nfi"></a>Wasn’t this site called Neighbourhood Fix-It?</dt> + <dd>Yes, we changed the name mid June 2007. We decided +Neighbourhood Fix-It was a bit of a mouthful, hard to spell, and hard to publicise (does the URL have a dash in it or not?). The domain FixMyStreet became available, and everyone liked the name.</dd> + <dt>Do you need any help with the project?</dt> + <dd>Yes, we can use help in all sorts of ways, technical or +non-technical. Please see our <a +href="http://www.mysociety.org/helpus/">Get Involved page</a>.</dd> + <dt>I’d like a site like this for my own location/ where’s the "source code" to this site?</dt> + <dd> +The software behind this site is open source, and available +to you mainly under the GNU Affero GPL software license. You can <a +href="http://github.com/mysociety/fixmystreet">download the +source code</a> and help us develop it. +You’re welcome to use it in your own projects, although you must also +make available the source code to any such projects. +<a href="http://www.fiksgatami.no/">Fiksgatami</a> is an example of our code +being used in a Norwegian version of this site. +</dd> +<dt>I’d prefer code in a different language?</dt> +<dd> +VisibleGovernment.ca wrote their own code for +<a href="http://www.fixmystreet.ca/">http://www.fixmystreet.ca/</a>, which is +written in GeoDjango and available under an MIT licence at <a +href="http://github.com/visiblegovernment/django-fixmystreet/tree/master">github</a>. +Or <a href="http://www.fixmystreet.org.nz/">FixMyStreet.org.nz</a> is written in +Drupal. +</p> +</dd> + <dt>People build things, not organisations. Who <em>actually</em> built it?</dt> + <dd>Matthew Somerville and Francis Irving wrote the site, +Chris Lightfoot wrote the tileserver and map cutter, Richard Pope created +our pins, Deborah Kerr keeps things up-to-date and does user support, +Ayesha Garrett designed our posters, and Tom Steinberg managed it all. + +Thanks also to +<a href="http://www.ordnancesurvey.co.uk">Ordnance Survey</a> (for the maps, +UK postcodes, and UK addresses – data © Crown copyright, all +rights reserved, Ministry of Justice 100037819 2008), +Yahoo! for their BSD-licensed JavaScript libraries, the entire free software +community (this particular project was brought to you by Perl, PostgreSQL, +and the number 161.290) and <a +href="http://www.bytemark.co.uk/">Bytemark</a> (who kindly host all +our servers). + +Let us know if we’ve missed anyone.</dd> + </dl> +[% INCLUDE 'footer.html' pagefooter = 'yes' %] diff --git a/templates/web/oxfordshire/footer.html b/templates/web/oxfordshire/footer.html new file mode 100644 index 000000000..cfca706c8 --- /dev/null +++ b/templates/web/oxfordshire/footer.html @@ -0,0 +1,51 @@ + [% IF pagefooter %] + <footer role="content-info"> + <p><a href="/privacy">Privacy and cookies</a></p> + </footer> + [% END %] + </div><!-- .content role=main --> + </div><!-- .container --> + </div><!-- .table-cell --> + + <div class="nav-wrapper"> + <div class="nav-wrapper-2"> + <div id="main-nav" role="navigation"> + <ul id="mysoc-menu"> + <li><a id="mysoc-logo" href="http://www.fixmystreet.com/">Powered by <img src="/cobrands/oxfordshire/images/fms-logo-105x20.png" alt="FixMyStreet"></a></li> + </ul> + + <ul id="main-menu"> + <li><[% IF c.req.uri.path == '/' %]span[% ELSE %]a href="/"[% END %] class="report-a-problem-btn" + >[% loc("Report a problem") %]</[% c.req.uri.path == '/' ? 'span' : 'a' %]></li>[% + %]<li><[% IF c.req.uri.path == '/my' %]span[% ELSE %]a href="/my"[% END + %]>[% loc("Your reports") %]</[% c.req.uri.path == '/my' ? 'span' : 'a' %]></li>[% + %]<li><[% IF c.req.uri.path == '/reports' %]span[% ELSE %]a href="/reports"[% END + %]>[% loc("All reports") %]</[% c.req.uri.path == '/reports' ? 'span' : 'a' %]></li>[% + %]<li><[% IF c.req.uri.path == '/alert' %]span[% ELSE %]a href="/alert[% pc ? '/list?pc=' : '' %][% pc | uri %]"[% END + %]>[% loc("Local alerts") %]</[% c.req.uri.path == '/alert' ? 'span' : 'a' %]></li>[% + %]<li><[% IF c.req.uri.path == '/faq' %]span[% ELSE %]a href="/faq"[% END + %]>[% loc("Help") %]</[% c.req.uri.path == '/faq' ? 'span' : 'a' %]></li> + </ul> + </div> + </div> + </div> + +<!-- [% INCLUDE 'debug_footer.html' %] --> + </div> <!-- .wrapper --> + <div id="oxford-footer" class="desk-only"> + <address> + <strong>Oxfordshire County Council</strong><br> + <a href="http://www.oxfordshire.gov.uk/cms/public-site/contact-oxfordshire-county-council" title="Contac the council">Contact the council</a> + </address> + <ul><!-- use | between items --> + <li> + <a href="/contact" title="Contact the FixMyStreet team">Contact</a> | + </li> + <li class="powered-by-fms"> + <a href="http://www.fixmystreet.com/">Powered by <img src="/cobrands/oxfordshire/images/fms-logo-inverse.png" alt="FixMyStreet"></a> + </li> + </ul> + </div> +</div> <!-- oxford-wrapper --> +</body> +</html> diff --git a/templates/web/oxfordshire/header.html b/templates/web/oxfordshire/header.html new file mode 100644 index 000000000..6c338452a --- /dev/null +++ b/templates/web/oxfordshire/header.html @@ -0,0 +1,94 @@ +<!doctype html> +<!--[if lt IE 7]><html class="no-js ie6 oldie" lang="[% lang_code %]"><![endif]--> +<!--[if IE 7]> <html class="no-js ie7 oldie" lang="[% lang_code %]"><![endif]--> +<!--[if IE 8]> <html class="no-js ie8 oldie" lang="[% lang_code %]"><![endif]--> +<!--[if IE 9]> <html class="no-js ie9 oldie" lang="[% lang_code %]"><![endif]--> +<!--[if gt IE 9]><!--><html class="no-js" lang="[% lang_code %]"><!--<![endif]--> + <head> + <meta name="viewport" content="initial-scale=1.0"> + + <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> + <meta name="HandHeldFriendly" content="true"> + <meta name="mobileoptimized" content="0"> + +[% SET start = c.config.ADMIN_BASE_URL IF admin %] + + <link rel="stylesheet" href="[% start %][% version('/cobrands/' _ c.cobrand.moniker _ '/base.css') %]"> + <link rel="stylesheet" href="[% start %][% version('/cobrands/' _ c.cobrand.moniker _ '/layout.css') %]" media="(min-width:48em)"> + [% extra_css %] + <!--[if (lt IE 9) & (!IEMobile)]> + <link rel="stylesheet" href="[% start %][% version('/cobrands/' _ c.cobrand.moniker _ '/layout.css') %]"> + <![endif]--> + + <script src="[% start %][% version('/js/modernizr.custom.js') %]" charset="utf-8"></script> + <script src="[% start %][% version('/cobrands/oxfordshire/position_map.js') %]" charset="utf-8"></script> + [% INCLUDE 'common_header_tags.html', js_override = '/cobrands/fixmystreet/fixmystreet.js', site_title = 'FixMyStreet' %] + [% extra_js %] + + [% IF c.req.uri.host == 'osm.fixmystreet.com' %] + <link rel="canonical" href="http://www.fixmystreet.com[% c.req.uri.path_query %]"> + [% END %] + + [% INCLUDE 'tracking_code.html' %] + + </head> + <body class="[% bodyclass | html IF bodyclass %]"> +<div id="oxford-wrapper"> + <div id="oxford-header" class="desk-only"> + <a href="http://www.oxfordshire.gov.uk/" title="Home" class="logo">Oxfordshire County Council<span></span></a> + <span id="oxford-links"> + <a href="http://www.oxfordshire.gov.uk/" title="">Oxfordshire County Council home</a>|<a href="/" title="">FixMyStreet</a> + </span> + <div style="clear:both"></div> + <span class="header"><a href="/">FixMyStreet</a></span> + <div class="oxford-user"> + <p> + [% IF c.user_exists %] + [% tprintf(loc('Hi %s'), c.user.name || c.user.email) %] + <a href="/auth/sign_out">[% loc('sign out') %]</a> + [% END %] + </p> + </div> + </div> <!-- end of oxford header --> + <div id="oxford-main-menu" class="desk-only"> + <ul class="tabs"> + <li class="home first"><[% IF c.req.uri.path == '/' %]span[% ELSE %]a href="/"[% END %] class="report-a-problem-btn" + >[% "Report" %]</[% c.req.uri.path == '/' ? 'span' : 'a' %]></li>[% + %]<li><[% IF c.req.uri.path == '/my' OR ( c.req.uri.path == '/auth' AND c.req.params.r == 'my' ) %]span[% ELSE %]a href="/my"[% END + %]>[% loc("Your reports") %]</[% ( c.req.uri.path == '/my' OR ( c.req.uri.path == '/auth' AND c.req.params.r == 'my' ) ) ? 'span' : 'a' %]></li>[% + %]<li><[% IF c.req.uri.path == '/reports/Oxfordshire' %]span[% ELSE %]a href="/reports/Oxfordshire"[% END + %]>[% loc("All reports") %]</[% c.req.uri.path == '/reports' ? 'span' : 'a' %]></li>[% + %]<li><[% IF c.req.uri.path == '/alert' %]span[% ELSE %]a href="/alert[% pc ? '/list?pc=' : '' %][% pc | uri %]"[% END + %]>[% loc("Local alerts") %]</[% c.req.uri.path == '/alert' ? 'span' : 'a' %]></li>[% + %]<li class="last"><[% IF c.req.uri.path == '/faq' %]span[% ELSE %]a href="/faq"[% END + %]>[% loc("Help") %]</[% c.req.uri.path == '/faq' ? 'span' : 'a' %]></li> + </ul> + </div> + + <div class="wrapper"> + + <div class="table-cell"> + <header id="site-header" role="banner"> + <div class="container"> + <a href="/" id="site-logo">Oxfordshire FixMyStreet</a> + <a href="#main-nav" id="nav-link">Main Navigation</a> + </div> + </header> + + <div id="user-meta"> + [% IF c.user_exists %] + <p> + [% tprintf(loc('Hi %s'), c.user.name || c.user.email) %] + <a href="/auth/sign_out">[% loc('sign out') %]</a> + </p> + [% ELSE %] + <!-- <a href="/auth">[% loc('Sign in') %]</a> --> + [% END %] + </div> + + [% pre_container_extra %] + + <div class="container"> + <div class="content[% " $mainclass" | html IF mainclass %]" role="main"> + + <!-- [% INCLUDE 'debug_header.html' %] --> diff --git a/templates/web/oxfordshire/report/new/councils_text_all.html b/templates/web/oxfordshire/report/new/councils_text_all.html new file mode 100644 index 000000000..e71a400ac --- /dev/null +++ b/templates/web/oxfordshire/report/new/councils_text_all.html @@ -0,0 +1,18 @@ +<p>You can use this form to report a problem or to make an enquiry about roads +and pavements in your area. All the information you provide here will be sent +to <strong>[% all_council_names.join( '</strong> or <strong>' ) %]</strong>. +The subject and details of the problem will be public, plus your name if you +give us permission. If you report a fault on a road that is not owned by +Oxfordshire County Council we will pass the report on to the relevant body. + +<p>Our opening hours are 8.30 to 5, Monday to Thursday and 8.30 to 4 on +Fridays. Please <strong>do not</strong> use this form for reporting +<strong>emergencies and urgent</strong> problems. You should report these by +contacting 0845 310 11 11. If your enquiry is related to Highways and is +outside of our opening hours and cannot wait, please contact Thames Valley +Police on 101.</p> + +<p>Please use <a href="/faq#pothole" target="_blank">our chart</a> to determine +the size of any pot holes being reported and whether to submit a report using +this online form or by telephone.</p> + diff --git a/templates/web/oxfordshire/report/new/fill_in_details_text.html b/templates/web/oxfordshire/report/new/fill_in_details_text.html new file mode 100644 index 000000000..065005956 --- /dev/null +++ b/templates/web/oxfordshire/report/new/fill_in_details_text.html @@ -0,0 +1,6 @@ +Oxfordshire County Council won’t be able to help unless you leave as much +detail as you can. Please describe the exact location of the problem (e.g. in +the carriageway), what it is, how long it has been there, a description and a +photo of the problem if you have one. Please be aware that you can only attach +one picture so ensure that you provide a picture that clearly shows the +location not just the fault. diff --git a/templates/web/oxfordshire/report/new/notes.html b/templates/web/oxfordshire/report/new/notes.html new file mode 100644 index 000000000..e03fd8644 --- /dev/null +++ b/templates/web/oxfordshire/report/new/notes.html @@ -0,0 +1,10 @@ +<p>[% loc("Please note:") %]</p> + +<ul class="plain-list"> + <li>[% loc("We will only use your personal information in accordance with our <a href=\"/privacy\">privacy policy.</a>") %]</li> + <li>[% loc("Please be polite, concise and to the point.") %]</li> + <li>[% loc("Please do not be abusive — abusing your council devalues the service for all users.") %]</li> + <li>[% loc("Writing your message entirely in block capitals makes it hard to read, as does a lack of punctuation.") %]</li> + <li>Remember that FixMyStreet is primarily for reporting physical problems that can be fixed. Remember that you can contact Oxfordshire County Council for additional issues that are not covered on this reporting facility.</li> +</ul> + diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index be5de57cd..ab20520d0 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -54,8 +54,13 @@ $(function(){ var $html = $('html'); var cobrand; + var is_small_map = false; if (window.location.href.indexOf('bromley') != -1) { cobrand = 'bromley'; + is_small_map = true; + } else if (window.location.href.indexOf('oxfordshire') != -1) { + cobrand = 'oxfordshire'; + is_small_map = true; } // Deal with switching between mobile and desktop versions on resize @@ -104,7 +109,7 @@ $(function(){ $html.removeClass('mobile'); position_map_box(); if (typeof fixmystreet !== 'undefined') { - if (cobrand == 'bromley') { + if (is_small_map) { //$('#bromley-footer').hide(); } else { fixmystreet.state_map = 'full'; @@ -112,10 +117,11 @@ $(function(){ } if (typeof fixmystreet !== 'undefined' && fixmystreet.page == 'around') { // Remove full-screen-ness - var banner_text; + var banner_text = 'Click map to report a problem'; if (cobrand == 'bromley') { - banner_text = 'Click map to report a problem<span>Yellow pins show existing reports</span>'; - } else { + banner_text += '<span>Yellow pins show existing reports</span>'; + } + if (! is_small_map) { $('#site-header').show(); banner_text = validation_strings.report_problem_heading; } diff --git a/web/cobrands/oxfordshire/_colours.scss b/web/cobrands/oxfordshire/_colours.scss new file mode 100644 index 000000000..2e021138d --- /dev/null +++ b/web/cobrands/oxfordshire/_colours.scss @@ -0,0 +1,17 @@ +/* COLOURS */ + +$oxfordshire_dk_green: #114500; +$oxfordshire_lt_green: #339E00; + +$primary: $oxfordshire_lt_green; +$primary_b: $oxfordshire_dk_green; +$primary_text: #fff; + +$contrast1: $oxfordshire_lt_green; +$contrast1_dark: #fff; // darken(#E1E3E4, 10%); +$contrast2: blue; + +//$contrast1: #E1E3E4; +//$contrast1_dark: darken(#E1E3E4, 10%); +//$contrast2: #AA8D11; + diff --git a/web/cobrands/oxfordshire/base.scss b/web/cobrands/oxfordshire/base.scss new file mode 100644 index 000000000..10e5c5711 --- /dev/null +++ b/web/cobrands/oxfordshire/base.scss @@ -0,0 +1,40 @@ +@import "../fixmystreet/_h5bp"; +@import "./_colours"; +@import "../fixmystreet/_mixins"; +@import "compass"; + +@import "../fixmystreet/_base"; + + +// Colour tab to match colour scheme +#nav-link { + width: 50px; + height: 48px; + background: url('/cobrands/oxfordshire/images/tab-green.png') 0 0 no-repeat; +} + +#site-header { + background: none; + background-color: $oxfordshire_dk_green; + height: 60px; +} + +#site-logo { + margin-top:4px; + background-image: url('/cobrands/oxfordshire/images/logo.jpg'); + background-repeat: no-repeat; + background-position: 0px 0px; + border: 4px solid $oxfordshire_dk_green; + width: 173px; + height: 38px; +} + +#main-nav ul#mysoc-menu li a#mysoc-logo { + background-image: none; + text-indent: 0; + img { + display: inline; + height: 20px; + width: 105px; + } +}
\ No newline at end of file diff --git a/web/cobrands/oxfordshire/config.rb b/web/cobrands/oxfordshire/config.rb new file mode 100644 index 000000000..471b4b008 --- /dev/null +++ b/web/cobrands/oxfordshire/config.rb @@ -0,0 +1,25 @@ +# Require any additional compass plugins here. + +# Set this to the root of your project when deployed: +http_path = "/" +css_dir = "" +sass_dir = "" +images_dir = "" +javascripts_dir = "" + +# You can select your preferred output style here (can be overridden via the command line): +# output_style = :expanded or :nested or :compact or :compressed + +# To enable relative paths to assets via compass helper functions. Uncomment: +# relative_assets = true + +# To disable debugging comments that display the original location of your selectors. Uncomment: +# line_comments = false + +# If you prefer the indented syntax, you might want to regenerate this +# project again passing --syntax sass, or you can uncomment this: +# preferred_syntax = :sass +# and then run: +# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass + +line_comments = false # by Compass.app
\ No newline at end of file diff --git a/web/cobrands/oxfordshire/images/bg-y.jpg b/web/cobrands/oxfordshire/images/bg-y.jpg Binary files differnew file mode 100755 index 000000000..b623bc784 --- /dev/null +++ b/web/cobrands/oxfordshire/images/bg-y.jpg diff --git a/web/cobrands/oxfordshire/images/bg.jpg b/web/cobrands/oxfordshire/images/bg.jpg Binary files differnew file mode 100755 index 000000000..e670c0f7d --- /dev/null +++ b/web/cobrands/oxfordshire/images/bg.jpg diff --git a/web/cobrands/oxfordshire/images/divider1x32.png b/web/cobrands/oxfordshire/images/divider1x32.png Binary files differnew file mode 100644 index 000000000..fffea7e24 --- /dev/null +++ b/web/cobrands/oxfordshire/images/divider1x32.png diff --git a/web/cobrands/oxfordshire/images/dot6x6.jpg b/web/cobrands/oxfordshire/images/dot6x6.jpg Binary files differnew file mode 100755 index 000000000..73a9c72f4 --- /dev/null +++ b/web/cobrands/oxfordshire/images/dot6x6.jpg diff --git a/web/cobrands/oxfordshire/images/fms-logo-105x20.png b/web/cobrands/oxfordshire/images/fms-logo-105x20.png Binary files differnew file mode 100644 index 000000000..286f22ded --- /dev/null +++ b/web/cobrands/oxfordshire/images/fms-logo-105x20.png diff --git a/web/cobrands/oxfordshire/images/fms-logo-inverse.png b/web/cobrands/oxfordshire/images/fms-logo-inverse.png Binary files differnew file mode 100644 index 000000000..77417c3e9 --- /dev/null +++ b/web/cobrands/oxfordshire/images/fms-logo-inverse.png diff --git a/web/cobrands/oxfordshire/images/footer.jpg b/web/cobrands/oxfordshire/images/footer.jpg Binary files differnew file mode 100755 index 000000000..8bd0758eb --- /dev/null +++ b/web/cobrands/oxfordshire/images/footer.jpg diff --git a/web/cobrands/oxfordshire/images/header.jpg b/web/cobrands/oxfordshire/images/header.jpg Binary files differnew file mode 100755 index 000000000..f642adfc4 --- /dev/null +++ b/web/cobrands/oxfordshire/images/header.jpg diff --git a/web/cobrands/oxfordshire/images/logo.jpg b/web/cobrands/oxfordshire/images/logo.jpg Binary files differnew file mode 100755 index 000000000..9ab24d2c4 --- /dev/null +++ b/web/cobrands/oxfordshire/images/logo.jpg diff --git a/web/cobrands/oxfordshire/images/tab-green.png b/web/cobrands/oxfordshire/images/tab-green.png Binary files differnew file mode 100644 index 000000000..7837fed00 --- /dev/null +++ b/web/cobrands/oxfordshire/images/tab-green.png diff --git a/web/cobrands/oxfordshire/images/tabs-featured-on.png b/web/cobrands/oxfordshire/images/tabs-featured-on.png Binary files differnew file mode 100644 index 000000000..94fe089c6 --- /dev/null +++ b/web/cobrands/oxfordshire/images/tabs-featured-on.png diff --git a/web/cobrands/oxfordshire/images/tabs-featured.png b/web/cobrands/oxfordshire/images/tabs-featured.png Binary files differnew file mode 100644 index 000000000..99b823faf --- /dev/null +++ b/web/cobrands/oxfordshire/images/tabs-featured.png diff --git a/web/cobrands/oxfordshire/layout.scss b/web/cobrands/oxfordshire/layout.scss new file mode 100644 index 000000000..8d5710158 --- /dev/null +++ b/web/cobrands/oxfordshire/layout.scss @@ -0,0 +1,154 @@ +@import "_colours"; +@import "../fixmystreet/_layout"; + +body { + background-color: #fff; + background-image: none; +} + +#front-main { + background-color: $primary; + background-image: none; + @include border-radius(1em 1em 0 0); + margin: 2em 1em 0; + padding-top: 1em; + h1 { + margin: 0 auto 0 auto; + } + h2 { + color: $primary_text; + } + a#geolocate_link { + color: $primary_text; + } +} + +// Currently hide the nav-wrapper, because it's in going into Oxfordshire's own nav +// likewise with user-meta +.nav-wrapper, #user-meta { + display: none; +} + +// hide the site-header, currently has council logo at top of page +#site-header { + display: none; +} + +// White background, so no shadow or margin needed. +.content { + margin: 0; + @include box-shadow(none); +} +.ie6, .ie7, .ie8 { + .content { + margin: 0; + border: none; + } +} + +// Fix location of aside sidebar +body.twothirdswidthpage { + .content { + aside { + @include box-shadow(none); + } + .sticky-sidebar { + aside { + position: fixed; + top: 10em; + li { // from occ website + padding-left: 19px; + font: 0.813em "Trebuchet MS"; + background: url("/cobrands/oxfordshire/images/dot6x6.jpg") no-repeat 0 5px; + } + } + } + } +} + +//------------------------------------------------- +// following declarations concern the map display: +//------------------------------------------------- +// So that map appears underneath the header +.wrapper { + position: relative; + .table-cell { + padding-left: 13px; // added 13px to match Oxfordshire's normal look + padding-right: 13px; + } +} +.ie6, .ie7 { + .wrapper { + padding-top: 1em; + } +} + +// show the sidebar tips and notices in the document flow, i.e., in the +// left-hand column, rather than in smaller text above the map +.general-sidebar-notes, +#report-a-problem-sidebar { + position: static; + width: auto; + @include box-shadow(rgba(0, 0, 0, 0), 0, 0, 0); + .sidebar-tips, + .sidebar-notes { + font-size:1em; + } +} + +// To prevent font size larger interfering with the fixed Oxfordshire layout +.container { width: auto; } +.full-width { width: 464px; } +.shadow-wrap { width: 464px; } + +#map_box { width: 464px; } +.content { width: 432px; } + +body.fullwidthpage .content { width: auto; } +body.twothirdswidthpage .content { + width: 640px; + aside { + left: 672px; + width: 208px; + padding: 16px; + } + .sticky-sidebar { + left: 672px; + aside { + top:10em; + } + } +} +.ie6, .ie7 { + body.mappage .container { + width: 464px; + margin-left: 0; + } +} + +// As map can scroll and isn't at the top, give it an edge +#map_box { + border: solid 1px #999; + top: 1em; + right: 0em; + margin: 0; +} + +// Perhaps fix map location (should be in central?) +.ie6 #map_box, .ie7 #map_box { + right: -480px; +} + +// So as not to interfere with the Oxfordshire footer, make the fixed nav ("get updates" etc) static. +.shadow-wrap { + position: static; + padding-top: 0; + margin-bottom: 1em; + ul#key-tools { + border-top: none; + border-bottom: 1px solid $primary; + } +} + + +@import "oxfordshire"; diff --git a/web/cobrands/oxfordshire/oxfordshire.scss b/web/cobrands/oxfordshire/oxfordshire.scss new file mode 100644 index 000000000..0429a622b --- /dev/null +++ b/web/cobrands/oxfordshire/oxfordshire.scss @@ -0,0 +1,184 @@ +/* Parts of oxfordshire's main CSS needed for its header/footer and adjusted (see + * bottom) to not be affected by main FixMyStreet CSS. Not very sustainable; + * perhaps we should wrap all council CSS within a SCSS #council ID? Hmm. + */ + + @import "_colours"; + + +body { + font-family:"Trebuchet MS",Arial, Helvetica, sans-serif; + line-height:18px; + a {text-decoration:none; outline:0; font-family:Arial, Helvetica, sans-serif; font-size:0.75em; color:#0c62ba} + a { font-size: 1em; } // mySociety + a:hover {text-decoration:underline} + margin:0; + background:#E0E0E0 url("/cobrands/oxfordshire/images/bg.jpg") repeat-y top center; + + #oxford-wrapper { + background: url("/cobrands/oxfordshire/images/bg-y.jpg") repeat-y scroll 0 0 #FFFFFF; + clear: both; + display: block; + margin: 0 auto; + padding: 0 8px; + width: 990px; + } + +} + +#oxford-header + { + padding:0 16px 7px 16px; + clear:both; + overflow:hidden; + position:relative; + width:958px; + height:84px; + height:auto !important; + min-height:84px; + background: $oxfordshire_lt_green url("/cobrands/oxfordshire/images/header.jpg") no-repeat 0 0; + + a.logo:hover {cursor:pointer;cursor:hand} + a.logo {float:left; display:inline; margin:3px 0 6px 10px; position:relative; overflow:hidden} + a.logo span {display:block; position:absolute; top:0; left:0; z-index:10} + a.logo, a.logo span {width:173px; height:38px; background: url("/cobrands/oxfordshire/images/logo.jpg") no-repeat 0 0;} + + h1 {float:left; padding:8px 0 0 10px; margin:0; font-size:1.25em; line-height:normal; font-weight:bold; color:#ffffff; white-space:nowrap;font-family:"Trebuchet MS",Tahoma,Arial,sans-serif;} + span.header {float:left; padding:8px 0 0 10px; margin:0; font-size:1.25em; line-height:normal; font-weight:bold; color:#ffffff; white-space:nowrap} + a {color:#ffffff;} + + #oxford-links { + padding: 10px 3px 0px 0px; float:right;color:#ffffff; + a{ + font-size:0.75em; // mySociety putting this back (switched off in body) + margin: 0px 5px 0px 5px + } + + } + .oxford-user { + float: right; + p { + padding: 0.25em; + margin: 0.5em 0; + a { + margin: 0 0.5em; + } + } + } +} + + + +#oxford-main-menu { + clear: both; + margin: 0; + padding: 0; + font-size: 1em; + position: relative; + ul { + margin: 0 0 0 330px; + position: relative; + li { + margin: 0; + list-style-type: none; + float:left; + width:126px; + text-align:center; + background: #e0e0e0; + padding: 8px 0; + margin: 0 0 0 2px; + } + } + // from occ.css (client site): #main .view-features-for-homepage ul.tabs + ul.tabs { + float:left; + position:relative; + padding:0; + margin:0.5em 0 0 0; + z-index:10; + width: 990px; + //width:635px; + min-height:32px; + overflow:hidden; + clear:both; + background: #939393 url("/cobrands/oxfordshire/images/tabs-featured.png") repeat 0 0; + li { + float:left; + padding:0 0 0px 1px; + margin:0; + font:0.813em/27px "Trebuchet MS"; + color:#ffffff; + height:32px; + background: #666 url("/cobrands/oxfordshire/images/divider1x32.png") no-repeat 0 0; + } + li.first {padding:0; background:none} + span, // mySociety + a { + display:block; + position:relative; + padding:8px 0 0 0; + font:bold 1em "Trebuchet MS"; + height:24px; + color:#ffffff; + text-align:center; + background: #939393 url("/cobrands/oxfordshire/images/tabs-featured.png") repeat-x 0 0; + white-space:nowrap; + } + a:hover, + a:focus { + background: none #EA6C18; + background:-moz-linear-gradient(100% 100% 90deg, #ff4401, #EA6C18); + background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#EA6C18), to(#ff4401)); + color: #ffffff; + } + li span, // mySociety + li.active a { + text-decoration:none; + background: #4c4c4c url("/cobrands/oxfordshire/images/tabs-featured-on.png") repeat-x 0 0; + } + li.active a:hover, + li.active a:focus {color: #ffffff;} + li.first a {} + li.last a {border-right:1px solid #666;} + a {padding:8px 0 0 0;} + } + +} + + +#oxford-footer { + float:left; + display:inline; + margin:0 -8px 0 -8px; + padding:10px 25px 30px 21px; + clear:both; + overflow:hidden; + width:960px; + background:#000000 url(/cobrands/oxfordshire/images/footer.jpg) no-repeat bottom left; + address {float:left; padding:11px 0 0 0; margin:0; color:#989898; font:0.813em arial} + a {font:1em arial; color:#ffffff; margin:0px 5px 0px 5px} + address a {font:1em arial; color:#ffffff; margin:0px 0px 0px 0px} + ul {float:right; padding:5px 0 0 55px; margin:0} + ul li {float:left; padding:0; font:0.813em/27px arial; color:#ffffff; overflow:hidden} + /* contact-the-team */ + li { + margin-left: 0.5em; + padding: 6px; + &.powered-by-fms { + // @include border-radius(6px); + min-width: 200px; + img { + display: inline; + height:20px; + width: 105px; + } + &:hover { + background-color:#2c2c2c; + } + a:hover { + text-decoration: none; + } + } + } +} + diff --git a/web/cobrands/oxfordshire/position_map.js b/web/cobrands/oxfordshire/position_map.js new file mode 100644 index 000000000..9c88d0980 --- /dev/null +++ b/web/cobrands/oxfordshire/position_map.js @@ -0,0 +1,19 @@ +function position_map_box() { + var $html = $('html'); + var oxfordshire_right; + if ($html.hasClass('ie6') || $html.hasClass('ie7')) { + oxfordshire_right = '-480px'; + } else { + oxfordshire_right = '0em'; + } + // Do the same as CSS (in case resized from mobile). + $('#map_box').prependTo('.content').css({ + zIndex: 1, position: 'absolute', + top: '1em', left: '', right: oxfordshire_right, bottom: '', + width: '464px', height: '464px', + margin: 0 + }); +} + +function map_fix() {} +var slide_wards_down = 1; |