aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rwxr-xr-xbin/comment-backfill21
-rwxr-xr-xbin/fetch-comments15
-rwxr-xr-xbin/send-comments92
-rw-r--r--conf/crontab.ugly5
-rw-r--r--db/schema.sql20
-rw-r--r--db/schema_0013-add_external_id_to_comment.sql6
-rw-r--r--db/schema_0013-add_send_method_column_to_open311conf.sql7
-rw-r--r--db/schema_0014-add_send_fail_columns_to_problem.sql10
-rw-r--r--db/schema_0015-add_extra_to_comment.sql6
-rw-r--r--db/schema_0016-add_whensent_and_send_fail_to_comment.sql11
-rw-r--r--db/schema_0017-add_send_comments_to_open311conf.sql6
-rw-r--r--db/schema_0018-add_comment_user_to_open311conf.sql6
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm24
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm27
-rw-r--r--perllib/FixMyStreet/Cobrand/Bromley.pm28
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/FixMyStreet.pm26
-rw-r--r--perllib/FixMyStreet/DB/Result/Comment.pm51
-rw-r--r--perllib/FixMyStreet/DB/Result/Open311conf.pm23
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm10
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm18
-rw-r--r--perllib/Open311.pm208
-rw-r--r--perllib/Open311/GetServiceRequestUpdates.pm110
-rw-r--r--perllib/Open311/PopulateServiceList.pm26
-rw-r--r--t/app/controller/report_new.t116
-rw-r--r--t/open311.t317
-rw-r--r--t/open311/getservicerequestupdates.t409
-rw-r--r--t/open311/populate-service-list.t298
-rw-r--r--templates/web/bromley/footer.html38
-rw-r--r--templates/web/bromley/header.html64
-rw-r--r--templates/web/bromley/index.html110
-rw-r--r--templates/web/bromley/report/display.html209
-rw-r--r--templates/web/bromley/report/new/fill_in_details_form.html230
-rw-r--r--templates/web/default/admin/report_edit.html1
-rw-r--r--templates/web/default/common_header_tags.html3
-rwxr-xr-xtemplates/web/default/faq/faq-en-gb.html3
-rw-r--r--templates/web/default/js/validation_strings.html5
-rw-r--r--templates/web/default/report/new/extra_name.html15
-rwxr-xr-xtemplates/web/default/reports/council.html14
-rw-r--r--templates/web/fixmystreet/alert/index.html24
-rw-r--r--templates/web/fixmystreet/alert/list.html1
-rw-r--r--templates/web/fixmystreet/around/around_index.html45
-rw-r--r--templates/web/fixmystreet/auth/sign_out.html6
-rw-r--r--templates/web/fixmystreet/header.html4
-rw-r--r--templates/web/fixmystreet/index.html15
-rw-r--r--templates/web/fixmystreet/report/display.html4
-rw-r--r--templates/web/fixmystreet/report/new/councils_text_all.html4
-rw-r--r--templates/web/fixmystreet/report/new/fill_in_details_form.html9
-rw-r--r--templates/web/fixmystreet/report/new/notes.html4
-rw-r--r--web/cobrands/bromley/base.scss22
-rw-r--r--web/cobrands/bromley/bromley-logo.jpgbin0 -> 20898 bytes
-rw-r--r--web/cobrands/bromley/bromley-logo.s.jpgbin0 -> 5908 bytes
-rw-r--r--web/cobrands/bromley/bromley.scss108
-rw-r--r--web/cobrands/bromley/favicon.icobin0 -> 61798 bytes
-rw-r--r--web/cobrands/bromley/fms-logo.pngbin0 -> 4740 bytes
-rw-r--r--web/cobrands/bromley/layout.scss102
-rw-r--r--web/cobrands/bromley/tab-blue.pngbin0 -> 826 bytes
-rw-r--r--web/cobrands/fixmystreet/_base.scss60
-rw-r--r--web/cobrands/fixmystreet/_layout.scss73
-rw-r--r--web/cobrands/fixmystreet/fixmystreet.js234
-rw-r--r--web/css/core.scss6
-rw-r--r--web/js/fixmystreet-old-box.js39
-rw-r--r--web/js/fixmystreet.js171
-rw-r--r--web/js/map-OpenLayers.js14
-rw-r--r--web/js/modernizr.custom.76759.js4
-rw-r--r--web/js/modernizr.custom.js4
67 files changed, 3071 insertions, 473 deletions
diff --git a/.gitignore b/.gitignore
index 055e181dd..974d01d6b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
*.ttc
/cities_bin
/private_locale
+*~
._*
.DS_Store
.carton
diff --git a/bin/comment-backfill b/bin/comment-backfill
new file mode 100755
index 000000000..dfdaf2750
--- /dev/null
+++ b/bin/comment-backfill
@@ -0,0 +1,21 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+require 5.8.0;
+use DateTime;
+
+use FixMyStreet::App;
+
+use Open311;
+use Open311::GetServiceRequestUpdates;
+
+my $start_time = DateTime->now->subtract( days => 1, hours => 1 );
+my $end_time = DateTime->now;
+
+my $updates = Open311::GetServiceRequestUpdates->new(
+ start_time => $start_time,
+ end_time => $end_time,
+);
+
+$updates->fetch;
diff --git a/bin/fetch-comments b/bin/fetch-comments
new file mode 100755
index 000000000..4bbcc9d21
--- /dev/null
+++ b/bin/fetch-comments
@@ -0,0 +1,15 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+require 5.8.0;
+
+use FixMyStreet::App;
+
+use Open311;
+use Open311::GetServiceRequestUpdates;
+
+
+my $updates = Open311::GetServiceRequestUpdates->new;
+
+$updates->fetch;
diff --git a/bin/send-comments b/bin/send-comments
new file mode 100755
index 000000000..3a5d1aa47
--- /dev/null
+++ b/bin/send-comments
@@ -0,0 +1,92 @@
+#!/usr/bin/env perl
+
+# send-reports:
+# Send new problem reports to councils
+#
+# Copyright (c) 2011 UK Citizens Online Democracy. All rights reserved.
+# Email: matthew@mysociety.org. WWW: http://www.mysociety.org
+
+use strict;
+use warnings;
+require 5.8.0;
+
+use Digest::MD5;
+use Encode;
+use Error qw(:try);
+use CronFns;
+
+use FixMyStreet::App;
+
+use Utils;
+use mySociety::Config;
+use mySociety::EmailUtil;
+
+use Open311;
+
+# maximum number of webservice attempts to send before not trying any more (XXX may be better in config?)
+use constant SEND_FAIL_RETRIES_CUTOFF => 3;
+
+# send_method config values found in by-area config data, for selecting to appropriate method
+use constant SEND_METHOD_EMAIL => 'email';
+use constant SEND_METHOD_OPEN311 => 'open311';
+
+# Set up site, language etc.
+my ($verbose, $nomail) = CronFns::options();
+my $base_url = mySociety::Config::get('BASE_URL');
+my $site = CronFns::site($base_url);
+
+my $councils = FixMyStreet::App->model('DB::Open311Conf')->search( {
+ send_method => SEND_METHOD_OPEN311,
+ send_comments => 1,
+} );
+
+while ( my $council = $councils->next ) {
+ my $comments = FixMyStreet::App->model('DB::Comment')->search( {
+ 'me.whensent' => undef,
+ 'problem.whensent' => { '!=' => undef },
+ 'problem.external_id' => { '!=' => undef },
+ 'problem.council' => { -like => '%' . $council->area_id .'%' },
+ },
+ {
+ join => 'problem',
+ }
+ );
+
+ my $o = Open311->new(
+ endpoint => $council->endpoint
+ );
+
+ while ( my $comment = $comments->next ) {
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($comment->cobrand)->new();
+
+ if ( $comment->send_fail_count ) {
+ next if bromley_retry_timeout( $comment );
+ }
+
+ my $id = $o->post_service_request_update( $comment );
+
+ if ( $id ) {
+ $comment->external_id( $id );
+ $comment->update();
+ } else {
+ $comment->update( {
+ send_fail_count => $comment->send_fail_count + 1,
+ send_fail_timestamp => \'ms_current_timestamp()',
+ send_fail_reason => 'Failed to post over Open311',
+ } );
+ }
+ }
+}
+
+sub bromley_retry_timeout {
+ my $row = shift;
+
+ my $tz = DateTime::TimeZone->new( name => 'local' );
+ my $now = DateTime->now( time_zone => $tz );
+ my $diff = $now - $row->send_fail_timestamp;
+ if ( $diff->in_units( 'minutes' ) < 30 ) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/conf/crontab.ugly b/conf/crontab.ugly
index 9118d66f7..42e293c55 100644
--- a/conf/crontab.ugly
+++ b/conf/crontab.ugly
@@ -18,12 +18,15 @@ MAILTO=cron-!!(*= $site *)!!@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 'matthew.fixmystreet.com')) { *)!!
+!!(* } elsif (($vhost eq 'www.fixmystreet.com') || ($vhost eq 'matthew.fixmystreet.com')|| ($vhost eq 'bromley.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-8,10,11,13,14,16,17,19-23 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-reports.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-reports" || echo "stalled?"
0 9,12,15,18 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-reports.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-reports --verbose" || echo "stalled?"
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?"
+5,10,15,20,25,30,35,40,45,50,55 * * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/send-comments.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper send-comments" || echo "stalled?"
+5,10,15,20,25,30,35,40,45,50,55 * * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/fetch-comments.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper fetch-comments" || echo "stalled?"
+0,30 * * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/open311-populate-service-list.lock "/data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/cron-wrapper open311-populate-service-list" || echo "stalled?"
!!(* } *)!!
diff --git a/db/schema.sql b/db/schema.sql
index 395d1c07b..169939315 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -189,7 +189,12 @@ create table problem (
send_questionnaire boolean not null default 't',
extra text, -- extra fields required for open311
flagged boolean not null default 'f',
- geocode bytea
+ geocode bytea,
+
+ -- logging sending failures (used by webservices)
+ send_fail_count integer not null default 0,
+ send_fail_reason text,
+ send_fail_timestamp timestamp
);
create index problem_state_latitude_longitude_idx on problem(state, latitude, longitude);
create index problem_user_id_idx on problem ( user_id );
@@ -303,9 +308,15 @@ create table comment (
or problem_state = 'fixed'
or problem_state = 'fixed - council'
or problem_state = 'fixed - user'
- )
+ ),
-- other fields? one to indicate whether this was written by the council
-- and should be highlighted in the display?
+ external_id text,
+ extra text,
+ send_fail_count integer not null default 0,
+ send_fail_reason text,
+ send_fail_timestamp timestamp,
+ whensent timestamp
);
create index comment_user_id_idx on comment(user_id);
@@ -419,5 +430,8 @@ create table open311conf (
area_id integer not null unique,
endpoint text not null,
jurisdiction text,
- api_key text
+ api_key text,
+ send_method text,
+ send_comments boolean not null default 'f',
+ comment_user_id int references users(id)
);
diff --git a/db/schema_0013-add_external_id_to_comment.sql b/db/schema_0013-add_external_id_to_comment.sql
new file mode 100644
index 000000000..a1cd11c3f
--- /dev/null
+++ b/db/schema_0013-add_external_id_to_comment.sql
@@ -0,0 +1,6 @@
+begin;
+
+ALTER TABLE comment
+ ADD COLUMN external_id TEXT;
+
+commit;
diff --git a/db/schema_0013-add_send_method_column_to_open311conf.sql b/db/schema_0013-add_send_method_column_to_open311conf.sql
new file mode 100644
index 000000000..516fdd698
--- /dev/null
+++ b/db/schema_0013-add_send_method_column_to_open311conf.sql
@@ -0,0 +1,7 @@
+
+begin;
+
+ALTER table open311conf
+ ADD column send_method TEXT;
+
+commit;
diff --git a/db/schema_0014-add_send_fail_columns_to_problem.sql b/db/schema_0014-add_send_fail_columns_to_problem.sql
new file mode 100644
index 000000000..369c4118d
--- /dev/null
+++ b/db/schema_0014-add_send_fail_columns_to_problem.sql
@@ -0,0 +1,10 @@
+begin;
+
+ALTER table problem
+ ADD column send_fail_count integer not null default 0;
+ALTER table problem
+ ADD column send_fail_reason text;
+ALTER table problem
+ ADD column send_fail_timestamp timestamp;
+
+commit;
diff --git a/db/schema_0015-add_extra_to_comment.sql b/db/schema_0015-add_extra_to_comment.sql
new file mode 100644
index 000000000..5c1789ea2
--- /dev/null
+++ b/db/schema_0015-add_extra_to_comment.sql
@@ -0,0 +1,6 @@
+begin;
+
+ALTER TABLE comment
+ ADD COLUMN extra TEXT;
+
+commit;
diff --git a/db/schema_0016-add_whensent_and_send_fail_to_comment.sql b/db/schema_0016-add_whensent_and_send_fail_to_comment.sql
new file mode 100644
index 000000000..792ff2e38
--- /dev/null
+++ b/db/schema_0016-add_whensent_and_send_fail_to_comment.sql
@@ -0,0 +1,11 @@
+begin;
+
+ALTER table comment
+ ADD column send_fail_count integer not null default 0;
+ALTER table comment
+ ADD column send_fail_reason text;
+ALTER table comment
+ ADD column send_fail_timestamp timestamp;
+ALTER table comment
+ ADD column whensent timestamp;
+commit;
diff --git a/db/schema_0017-add_send_comments_to_open311conf.sql b/db/schema_0017-add_send_comments_to_open311conf.sql
new file mode 100644
index 000000000..0ee015575
--- /dev/null
+++ b/db/schema_0017-add_send_comments_to_open311conf.sql
@@ -0,0 +1,6 @@
+begin;
+
+ALTER table open311conf
+ ADD column send_comments BOOL NOT NULL DEFAULT 'f';
+
+commit;
diff --git a/db/schema_0018-add_comment_user_to_open311conf.sql b/db/schema_0018-add_comment_user_to_open311conf.sql
new file mode 100644
index 000000000..93851e2a3
--- /dev/null
+++ b/db/schema_0018-add_comment_user_to_open311conf.sql
@@ -0,0 +1,6 @@
+begin;
+
+ALTER TABLE open311conf
+ ADD COLUMN comment_user_id INT REFERENCES users(id);
+
+commit;
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index af4cdd5aa..7b630d36f 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -124,12 +124,16 @@ sub report_form_ajax : Path('ajax') : Args(0) {
my $category = $c->render_fragment( 'report/new/category.html');
my $councils_text = $c->render_fragment( 'report/new/councils_text.html');
my $has_open311 = keys %{ $c->stash->{category_extras} };
+ my $extra_name_info = $c->stash->{extra_name_info}
+ ? $c->render_fragment('report/new/extra_name.html')
+ : '';
my $body = JSON->new->utf8(1)->encode(
{
councils_text => $councils_text,
category => $category,
has_open311 => $has_open311,
+ extra_name_info => $extra_name_info,
}
);
@@ -394,6 +398,13 @@ sub initialize_report : Private {
}
+ if ( $c->req->param('first_name') && $c->req->param('last_name') ) {
+ $c->stash->{first_name} = $c->req->param('first_name');
+ $c->stash->{last_name} = $c->req->param('last_name');
+
+ $c->req->param( 'name', sprintf( '%s %s', $c->req->param('first_name'), $c->req->param('last_name') ) );
+ }
+
# Capture whether the map was used
$report->used_map( $c->req->param('skipped') ? 0 : 1 );
@@ -542,14 +553,14 @@ sub setup_categories_and_councils : Private {
);
$category_label = _('Property type:');
- } elsif ($first_council->{type} eq 'LBO') {
+ } elsif ($first_council->{id} != 2482 && $first_council->{type} eq 'LBO') {
$area_ids_to_list{ $first_council->{id} } = 1;
@category_options = (
_('-- Pick a category --'),
sort keys %{ Utils::london_categories() }
);
- $category_label = _('Category:');
+ $category_label = _('Category');
} else {
@@ -579,7 +590,7 @@ sub setup_categories_and_councils : Private {
if (@category_options) {
@category_options =
( _('-- Pick a category --'), @category_options, _('Other') );
- $category_label = _('Category:');
+ $category_label = _('Category');
}
}
@@ -589,6 +600,7 @@ sub setup_categories_and_councils : Private {
$c->stash->{category_options} = \@category_options;
$c->stash->{category_extras} = \%category_extras;
$c->stash->{category_extras_json} = encode_json \%category_extras;
+ $c->stash->{extra_name_info} = $first_council->{id} == 2482 ? 1 : 0;
my @missing_details_councils =
grep { !$area_ids_to_list{$_} } #
@@ -733,7 +745,7 @@ sub process_report : Private {
$councils = join( ',', @{ $c->stash->{area_ids_to_list} } ) || -1;
$report->council( $councils );
- } elsif ( $first_council->{type} eq 'LBO') {
+ } elsif ( $first_council->{id} != 2482 && $first_council->{type} eq 'LBO') {
unless ( Utils::london_categories()->{ $report->category } ) {
$c->stash->{field_errors}->{category} = _('Please choose a category');
@@ -785,6 +797,8 @@ sub process_report : Private {
};
}
+ $c->cobrand->process_extras( $c, \@contacts, \@extra );
+
if ( @extra ) {
$c->stash->{report_meta} = \@extra;
$report->extra( \@extra );
@@ -916,6 +930,8 @@ sub check_for_errors : Private {
%{ $c->stash->{report}->check_for_errors },
);
+ # FIXME: need to check for required bromley fields here
+
# if they're got the login details wrong when signing in then
# we don't care about the name field even though it's validated
# by the user object
diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm
index 15444f556..114c86c28 100644
--- a/perllib/FixMyStreet/App/Controller/Report/Update.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm
@@ -153,6 +153,15 @@ want to move adding these elsewhere
sub process_update : Private {
my ( $self, $c ) = @_;
+ if ( $c->req->param('first_name' ) && $c->req->param('last_name' ) ) {
+ my $first_name = $c->req->param('first_name');
+ my $last_name = $c->req->param('last_name');
+ $c->req->param('name', sprintf( '%s %s', $first_name, $last_name ) );
+
+ $c->stash->{first_name} = $first_name;
+ $c->stash->{last_name} = $last_name;
+ }
+
my %params =
map { $_ => scalar $c->req->param($_) } ( 'update', 'name', 'fixed', 'state', 'reopen' );
@@ -185,6 +194,24 @@ sub process_update : Private {
$update->problem_state( $params{state} );
}
+ if ( $c->req->param('fms_extra_title') ) {
+ my %extras = ();
+ $extras{title} = $c->req->param('fms_extra_title');
+ $extras{email_alerts_required} = $c->req->param('add_alert');
+ $update->extra( \%extras );
+
+ $c->stash->{fms_extra_title} = $c->req->param('fms_extra_title');
+ }
+
+ if ( $c->stash->{ first_name } && $c->stash->{ last_name } ) {
+ my $extra = $update->extra || {};
+ $extra->{first_name} = $c->stash->{ first_name };
+ $extra->{last_name} = $c->stash->{ last_name };
+ $update->extra( $extra );
+ }
+
+ $c->log->debug( 'name is ' . $c->req->param('name') );
+
$c->stash->{update} = $update;
$c->stash->{add_alert} = $c->req->param('add_alert');
diff --git a/perllib/FixMyStreet/Cobrand/Bromley.pm b/perllib/FixMyStreet/Cobrand/Bromley.pm
index 75174b638..90661c0c3 100644
--- a/perllib/FixMyStreet/Cobrand/Bromley.pm
+++ b/perllib/FixMyStreet/Cobrand/Bromley.pm
@@ -31,5 +31,33 @@ sub example_places {
return ( 'BR1 3UH', 'Glebe Rd, Bromley' );
}
+sub process_extras {
+ my $self = shift;
+ my $ctx = shift;
+ my $contacts = shift;
+ my $extra = shift;
+
+ for my $field (qw/ fms_extra_title first_name last_name /) {
+ my $value = $ctx->request->param($field);
+
+ if ( !$value ) {
+ $ctx->stash->{field_errors}->{$field} =
+ _('This information is required');
+ }
+ push @$extra,
+ {
+ name => $field,
+ description => uc($field),
+ value => $value || '',
+ };
+ }
+
+ if ( $ctx->request->param('fms_extra_title') ) {
+ $ctx->stash->{fms_extra_title} =
+ $ctx->request->param('fms_extra_title');
+ $ctx->stash->{extra_name_info} = 1;
+ }
+}
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 47038f25c..cee320cca 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -922,5 +922,7 @@ sub example_places {
return [ 'B2 4QA', 'Tib St, Manchester' ];
}
+sub process_extras {}
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
index 80d57400d..6c0089d26 100644
--- a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
+++ b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
@@ -45,5 +45,31 @@ sub generate_problem_banner {
return $banner;
}
+sub process_extras {
+ my $self = shift;
+ my $ctx = shift;
+ my $contacts = shift;
+ my $extra = shift;
+
+ if ( $contacts->[0]->area_id == 2482 ) {
+ for my $field ( qw/ fms_extra_title / ) {
+ my $value = $ctx->request->param( $field );
+
+ if ( !$value ) {
+ $ctx->stash->{field_errors}->{ $field } = _('This information is required');
+ }
+ push @$extra, {
+ name => $field,
+ description => uc( $field),
+ value => $value || '',
+ };
+ }
+
+ if ( $ctx->request->param('fms_extra_title') ) {
+ $ctx->stash->{fms_extra_title} = $ctx->request->param('fms_extra_title');
+ $ctx->stash->{extra_name_info} = 1;
+ }
+ }
+}
1;
diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm
index 195fe4019..d31bf5510 100644
--- a/perllib/FixMyStreet/DB/Result/Comment.pm
+++ b/perllib/FixMyStreet/DB/Result/Comment.pm
@@ -1,3 +1,4 @@
+use utf8;
package FixMyStreet::DB::Result::Comment;
# Created by DBIx::Class::Schema::Loader
@@ -7,7 +8,6 @@ use strict;
use warnings;
use base 'DBIx::Class::Core';
-
__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn");
__PACKAGE__->table("comment");
__PACKAGE__->add_columns(
@@ -54,29 +54,62 @@ __PACKAGE__->add_columns(
{ data_type => "boolean", is_nullable => 0 },
"problem_state",
{ data_type => "text", is_nullable => 1 },
+ "external_id",
+ { data_type => "text", is_nullable => 1 },
+ "extra",
+ { data_type => "text", is_nullable => 1 },
+ "send_fail_count",
+ { data_type => "integer", default_value => 0, is_nullable => 0 },
+ "send_fail_reason",
+ { data_type => "text", is_nullable => 1 },
+ "send_fail_timestamp",
+ { data_type => "timestamp", is_nullable => 1 },
+ "whensent",
+ { data_type => "timestamp", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
- "user",
- "FixMyStreet::DB::Result::User",
- { id => "user_id" },
- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
-);
-__PACKAGE__->belongs_to(
"problem",
"FixMyStreet::DB::Result::Problem",
{ id => "problem_id" },
{ is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);
+__PACKAGE__->belongs_to(
+ "user",
+ "FixMyStreet::DB::Result::User",
+ { id => "user_id" },
+ { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-06-27 10:07:32
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ilLn3dlagg5COdpZDmzrVQ
+# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-26 15:44:18
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:nvkElEgSU6XcLd9znSqhmQ
+
+__PACKAGE__->filter_column(
+ extra => {
+ filter_from_storage => sub {
+ my $self = shift;
+ my $ser = shift;
+ return undef unless defined $ser;
+ my $h = new IO::String($ser);
+ return RABX::wire_rd($h);
+ },
+ filter_to_storage => sub {
+ my $self = shift;
+ my $data = shift;
+ my $ser = '';
+ my $h = new IO::String($ser);
+ RABX::wire_wr( $data, $h );
+ return $ser;
+ },
+ }
+);
use DateTime::TimeZone;
use Image::Size;
use Moose;
use namespace::clean -except => [ 'meta' ];
+use RABX;
with 'FixMyStreet::Roles::Abuser';
diff --git a/perllib/FixMyStreet/DB/Result/Open311conf.pm b/perllib/FixMyStreet/DB/Result/Open311conf.pm
index 0a5784560..b9cd432ee 100644
--- a/perllib/FixMyStreet/DB/Result/Open311conf.pm
+++ b/perllib/FixMyStreet/DB/Result/Open311conf.pm
@@ -1,3 +1,4 @@
+use utf8;
package FixMyStreet::DB::Result::Open311conf;
# Created by DBIx::Class::Schema::Loader
@@ -7,7 +8,6 @@ use strict;
use warnings;
use base 'DBIx::Class::Core';
-
__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn");
__PACKAGE__->table("open311conf");
__PACKAGE__->add_columns(
@@ -26,13 +26,30 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 1 },
"api_key",
{ data_type => "text", is_nullable => 1 },
+ "send_method",
+ { data_type => "text", is_nullable => 1 },
+ "send_comments",
+ { data_type => "boolean", default_value => \"false", is_nullable => 0 },
+ "comment_user_id",
+ { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("open311conf_area_id_key", ["area_id"]);
+__PACKAGE__->belongs_to(
+ "comment_user",
+ "FixMyStreet::DB::Result::User",
+ { id => "comment_user_id" },
+ {
+ is_deferrable => 1,
+ join_type => "LEFT",
+ on_delete => "CASCADE",
+ on_update => "CASCADE",
+ },
+);
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-07-29 18:09:25
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ryqCpvwjNtQrZm4I3s0hxg
+# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-26 17:03:34
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:fC6Ws8p/pXyjgqfm2LRKsw
# You can replace this text with custom code or comments, and it will be preserved on regeneration
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index ce7488703..8c479953b 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -84,6 +84,12 @@ __PACKAGE__->add_columns(
{ data_type => "boolean", default_value => \"false", is_nullable => 0 },
"geocode",
{ data_type => "bytea", is_nullable => 1 },
+ "send_fail_count",
+ { data_type => "integer", is_nullable => 1 },
+ "send_fail_reason",
+ { data_type => "text", is_nullable => 1 },
+ "send_fail_timestamp",
+ { data_type => "timestamp", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_many(
@@ -106,8 +112,8 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-09-19 14:38:43
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:nq8Ufn/SEoDGSrrGlHIxag
+# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-16 10:08:56
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VODeZlWk8l/+IzBBlRNV0A
# Add fake relationship to stored procedure table
__PACKAGE__->has_one(
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index 56d726a8d..7b0ffca73 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -172,4 +172,22 @@ sub belongs_to_council {
return 0;
}
+=head2 split_name
+
+ $name = $user->split_name;
+ printf( 'Welcome %s %s', $name->{first}, $name->{last} );
+
+Returns a hashref with first and last keys with first name(s) and last name.
+NB: the spliting algorithm is extremely basic.
+
+=cut
+
+sub split_name {
+ my $self = shift;
+
+ my ($first, $last) = $self->name =~ /^(\S*)(?: (.*))?$/;
+
+ return { first => $first, last => $last };
+}
+
1;
diff --git a/perllib/Open311.pm b/perllib/Open311.pm
index e26e3e4c6..23208df1b 100644
--- a/perllib/Open311.pm
+++ b/perllib/Open311.pm
@@ -12,10 +12,13 @@ has api_key => ( is => 'ro', isa => 'Str' );
has endpoint => ( is => 'ro', isa => 'Str' );
has test_mode => ( is => 'ro', isa => 'Bool' );
has test_uri_used => ( is => 'rw', 'isa' => 'Str' );
+has test_req_used => ( is => 'rw' );
has test_get_returns => ( is => 'rw' );
-has endpoints => ( is => 'rw', default => sub { { services => 'services.xml', requests => 'requests.xml' } } );
+has endpoints => ( is => 'rw', default => sub { { services => 'services.xml', requests => 'requests.xml', service_request_updates => 'update.xml', update => 'update.xml' } } );
has debug => ( is => 'ro', isa => 'Bool', default => 0 );
has debug_details => ( is => 'rw', 'isa' => 'Str', default => '' );
+has success => ( is => 'rw', 'isa' => 'Bool', default => 0 );
+has error => ( is => 'rw', 'isa' => 'Str', default => '' );
sub get_service_list {
my $self = shift;
@@ -39,16 +42,40 @@ sub send_service_request {
my $extra = shift;
my $service_code = shift;
- my $description = <<EOT;
-title: @{[$problem->title()]}
+ my $params = $self->_populate_service_request_params(
+ $problem, $extra, $service_code
+ );
-detail: @{[$problem->detail()]}
+ my $response = $self->_post( $self->endpoints->{requests}, $params );
-url: $extra->{url}
+ if ( $response ) {
+ my $obj = $self->_get_xml_object( $response );
-Submitted via FixMyStreet
-EOT
-;
+ if ( $obj ) {
+ if ( $obj->{ request }->{ service_request_id } ) {
+ return $obj->{ request }->{ service_request_id };
+ } else {
+ my $token = $obj->{ request }->{ token };
+ if ( $token ) {
+ return $self->get_service_request_id_from_token( $token );
+ }
+ }
+ }
+
+ warn sprintf( "Failed to submit problem %s over Open311, response\n: %s\n%s", $problem->id, $response, $self->debug_details );
+ return 0;
+ }
+}
+
+sub _populate_service_request_params {
+ my $self = shift;
+ my $problem = shift;
+ my $extra = shift;
+ my $service_code = shift;
+
+ my $description = $self->_generate_service_request_description(
+ $problem, $extra
+ );
my ( $firstname, $lastname ) = ( $problem->user->name =~ /(\w+)\s+(.+)/ );
@@ -74,30 +101,37 @@ EOT
my $extras = $problem->extra;
for my $attr ( @$extras ) {
- my $name = sprintf( 'attribute[%s]', $attr->{name} );
+ my $attr_name = $attr->{name};
+ if ( $attr_name eq 'first_name' || $attr_name eq 'last_name' ) {
+ $params->{$attr_name} = $attr->{value} if $attr->{value};
+ next;
+ }
+ $attr_name =~ s/fms_extra_//;
+ my $name = sprintf( 'attribute[%s]', $attr_name );
$params->{ $name } = $attr->{value};
}
}
- my $response = $self->_post( $self->endpoints->{requests}, $params );
+ return $params;
+}
- if ( $response ) {
- my $obj = $self->_get_xml_object( $response );
+sub _generate_service_request_description {
+ my $self = shift;
+ my $problem = shift;
+ my $extra = shift;
- if ( $obj ) {
- if ( $obj->{ request }->{ service_request_id } ) {
- return $obj->{ request }->{ service_request_id };
- } else {
- my $token = $obj->{ request }->{ token };
- if ( $token ) {
- return $self->get_service_request_id_from_token( $token );
- }
- }
- }
+ my $description = <<EOT;
+title: @{[$problem->title()]}
- warn sprintf( "Failed to submit problem %s over Open311, response\n: %s\n%s", $problem->id, $response, $self->debug_details );
- return 0;
- }
+detail: @{[$problem->detail()]}
+
+url: $extra->{url}
+
+Submitted via FixMyStreet
+EOT
+;
+
+ return $description;
}
sub get_service_requests {
@@ -129,6 +163,97 @@ sub get_service_request_id_from_token {
}
}
+sub get_service_request_updates {
+ my $self = shift;
+ my $start_date = shift;
+ my $end_date = shift;
+
+ my $params = {};
+
+ if ( $start_date || $end_date ) {
+ return 0 unless $start_date && $end_date;
+
+ $params->{start_date} = $start_date;
+ $params->{end_date} = $end_date;
+ }
+
+ my $xml = $self->_get( $self->endpoints->{service_request_updates}, $params || undef );
+ my $service_requests = $self->_get_xml_object( $xml );
+ my $requests;
+ if ( ref $service_requests->{request_update } eq 'ARRAY' ) {
+ $requests = $service_requests->{request_update};
+ }
+ else {
+ $requests = [ $service_requests->{request_update} ];
+ }
+
+ return $requests;
+}
+
+sub post_service_request_update {
+ my $self = shift;
+ my $comment = shift;
+
+ my $params = $self->_populate_service_request_update_params( $comment );
+
+ my $response = $self->_post( $self->endpoints->{update}, $params );
+
+ if ( $response ) {
+ my $obj = $self->_get_xml_object( $response );
+
+ if ( $obj ) {
+ if ( $obj->{ request_update }->{ update_id } ) {
+ my $update_id = $obj->{request_update}->{update_id};
+
+ # if there's nothing in the update_id element we get a HASHREF back
+ unless ( ref $update_id ) {
+ return $obj->{ request_update }->{ update_id };
+ }
+ } else {
+ my $token = $obj->{ request_update }->{ token };
+ if ( $token ) {
+ return $self->get_service_request_id_from_token( $token );
+ }
+ }
+ }
+
+ warn sprintf( "Failed to submit comment %s over Open311, response - %s\n%s", $comment->id, $response, $self->debug_details );
+ return 0;
+ }
+}
+
+sub _populate_service_request_update_params {
+ my $self = shift;
+ my $comment = shift;
+
+ my $name = $comment->name || $comment->user->name;
+ my ( $firstname, $lastname ) = ( $name =~ /(\w+)\s+(.+)/ );
+
+ my $params = {
+ update_id_ext => $comment->id,
+ updated_datetime => $comment->confirmed,
+ service_request_id => $comment->problem->external_id,
+ service_request_id_ext => $comment->problem->id,
+ status => $comment->problem->is_open ? 'OPEN' : 'CLOSED',
+ email => $comment->user->email,
+ description => $comment->text,
+ public_anonymity_required => $comment->anonymous ? 'TRUE' : 'FALSE',
+ last_name => $lastname,
+ first_name => $firstname,
+ };
+
+ if ( $comment->extra ) {
+ $params->{'email_alerts_requested'}
+ = $comment->extra->{email_alerts_requested} ? 'TRUE' : 'FALSE';
+ $params->{'title'} = $comment->extra->{title};
+
+ $params->{first_name} = $comment->extra->{first_name} if $comment->extra->{first_name};
+ $params->{last_name} = $comment->extra->{last_name} if $comment->extra->{last_name};
+ }
+
+ return $params;
+}
+
sub _get {
my $self = shift;
my $path = shift;
@@ -144,10 +269,25 @@ sub _get {
my $content;
if ( $self->test_mode ) {
+ $self->success(1);
$content = $self->test_get_returns->{ $path };
$self->test_uri_used( $uri->as_string );
} else {
- $content = get( $uri->as_string );
+ my $ua = LWP::UserAgent->new;
+
+ my $req = HTTP::Request->new(
+ GET => $uri->as_string
+ );
+
+ my $res = $ua->request( $req );
+
+ if ( $res->is_success ) {
+ $content = $res->decoded_content;
+ $self->success(1);
+ } else {
+ $self->success(0);
+ $self->error( $res->status_line );
+ }
}
return $content;
@@ -171,17 +311,27 @@ sub _post {
$self->debug_details( $self->debug_details . "\nrequest:" . $req->as_string );
my $ua = LWP::UserAgent->new();
- my $res = $ua->request( $req );
+ my $res;
+
+ if ( $self->test_mode ) {
+ $res = $self->test_get_returns->{ $path };
+ $self->test_req_used( $req );
+ } else {
+ $res = $ua->request( $req );
+ }
if ( $res->is_success ) {
+ $self->success(1);
return $res->decoded_content;
} else {
- warn sprintf(
+ $self->success(0);
+ $self->error( sprintf(
"request failed: %s\nerror: %s\n%s",
$res->status_line,
$self->_process_error( $res->decoded_content ),
$self->debug_details
- );
+ ) );
+ warn $self->error;
return 0;
}
}
diff --git a/perllib/Open311/GetServiceRequestUpdates.pm b/perllib/Open311/GetServiceRequestUpdates.pm
new file mode 100644
index 000000000..ac06dc03e
--- /dev/null
+++ b/perllib/Open311/GetServiceRequestUpdates.pm
@@ -0,0 +1,110 @@
+package Open311::GetServiceRequestUpdates;
+
+use Moose;
+use Open311;
+use FixMyStreet::App;
+use DateTime::Format::W3CDTF;
+
+has council_list => ( is => 'ro' );
+has system_user => ( is => 'rw' );
+has start_date => ( is => 'ro', default => undef );
+has end_date => ( is => 'ro', default => undef );
+
+sub fetch {
+ my $self = shift;
+
+ my $councils = FixMyStreet::App->model('DB::Open311Conf')->search(
+ {
+ send_method => 'open311',
+ send_comments => 1,
+ comment_user_id => { '!=', undef },
+ endpoint => { '!=', '' },
+ }
+ );
+
+ while ( my $council = $councils->next ) {
+
+ my $o = Open311->new(
+ endpoint => $council->endpoint,
+ api_key => $council->api_key,
+ jurisdiction => $council->jurisdiction,
+ );
+
+ $self->system_user( $council->comment_user );
+ $self->update_comments( $o, { areaid => $council->area_id }, );
+ }
+}
+
+sub update_comments {
+ my ( $self, $open311, $council_details ) = @_;
+
+ my @args = ();
+
+ if ( $self->start_date || $self->end_date ) {
+ return 0 unless $self->start_date && $self->end_date;
+
+ push @args, $self->start_date;
+ push @args, $self->end_date;
+ }
+
+ my $requests = $open311->get_service_request_updates( @args );
+
+ return 0 unless $open311->success;
+
+ for my $request (@$requests) {
+ my $request_id = $request->{service_request_id};
+
+ # If there's no request id then we can't work out
+ # what problem it belongs to so just skip
+ next unless $request_id;
+
+ my $problem =
+ FixMyStreet::App->model('DB::Problem')
+ ->search( {
+ external_id => $request_id,
+ council => { like => '%' . $council_details->{areaid} . '%' },
+ } );
+
+ if (my $p = $problem->first) {
+ my $c = $p->comments->search( { external_id => $request->{update_id} } );
+
+ if ( !$c->first ) {
+ my $comment_time = DateTime::Format::W3CDTF->parse_datetime( $request->{updated_datetime} );
+
+ my $comment = FixMyStreet::App->model('DB::Comment')->new(
+ {
+ problem => $p,
+ user => $self->system_user,
+ external_id => $request->{update_id},
+ text => $request->{description},
+ mark_fixed => 0,
+ mark_open => 0,
+ anonymous => 0,
+ name => $self->system_user->name,
+ confirmed => $comment_time,
+ created => $comment_time,
+ state => 'confirmed',
+ }
+ );
+
+ if ( $p->is_open and $request->{status} eq 'closed' ) {
+ $p->state( 'fixed - council' );
+ $p->update;
+
+ $comment->mark_fixed( 1 );
+ } elsif ( ( $p->is_closed || $p->is_fixed ) and $request->{status} eq 'open' ) {
+ $p->state( 'confirmed' );
+ $p->update;
+
+ $comment->mark_open( 1 );
+ }
+
+ $comment->insert();
+ }
+ }
+ }
+
+ return 1;
+}
+
+1;
diff --git a/perllib/Open311/PopulateServiceList.pm b/perllib/Open311/PopulateServiceList.pm
index cfec9005d..ac355a33c 100644
--- a/perllib/Open311/PopulateServiceList.pm
+++ b/perllib/Open311/PopulateServiceList.pm
@@ -189,6 +189,12 @@ sub _add_contact_to_meta {
print "Fetching meta data for $self->_current_service->{service_code}\n";
my $meta_data = $self->_current_open311->get_service_meta_info( $self->_current_service->{service_code} );
+ if ( ref $meta_data->{ attributes }->{ attribute } eq 'HASH' ) {
+ $meta_data->{ attributes }->{ attribute } = [
+ $meta_data->{ attributes }->{ attribute }
+ ];
+ }
+
# turn the data into something a bit more friendly to use
my @meta =
# remove trailing colon as we add this when we display so we don't want 2
@@ -197,6 +203,26 @@ sub _add_contact_to_meta {
sort { $a->{order} <=> $b->{order} }
@{ $meta_data->{attributes}->{attribute} };
+ # we add these later on from bromley so don't list them here
+ # as we don't want to display them
+ if ( $self->_current_council->area_id == 2482 ) {
+ my %ignore = map { $_ => 1 } qw/
+ service_request_id_ext
+ requested_datetime
+ report_url
+ title
+ last_name
+ email
+ easting
+ northing
+ report_title
+ public_anonymity_required
+ email_alerts_requested
+ /;
+
+ @meta = grep { ! $ignore{ $_->{ code } } } @meta;
+ }
+
$contact->extra( \@meta );
$contact->update;
}
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index 625c7531f..1e751997b 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -48,6 +48,12 @@ my $contact3 = FixMyStreet::App->model('DB::Contact')->find_or_create( {
category => 'Trees',
email => 'trees@example.com',
} );
+my $contact4 = FixMyStreet::App->model('DB::Contact')->find_or_create( {
+ %contact_params,
+ area_id => 2482, # Bromley
+ category => 'Trees',
+ email => 'trees@example.com',
+} );
ok $contact1, "created test contact 1";
ok $contact2, "created test contact 2";
ok $contact3, "created test contact 3";
@@ -293,7 +299,7 @@ foreach my $test (
is_deeply $mech->form_errors, [], "no errors for pc '$test->{pc}'";
# click through to the report page
- $mech->follow_link_ok( { text => 'skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
# submit the main form
@@ -473,7 +479,7 @@ subtest "test password errors for a user who is signing in as they report" => su
"submit location" );
# click through to the report page
- $mech->follow_link_ok( { text => 'Skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
$mech->submit_form_ok(
@@ -520,7 +526,7 @@ subtest "test report creation for a user who is signing in as they report" => su
"submit location" );
# click through to the report page
- $mech->follow_link_ok( { text => 'Skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
$mech->submit_form_ok(
@@ -614,7 +620,7 @@ foreach my $test (
"submit location" );
# click through to the report page
- $mech->follow_link_ok( { text => 'Skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
# check that the fields are correctly prefilled
@@ -725,6 +731,108 @@ subtest "check that a lat/lon off coast leads to /around" => sub {
};
+for my $test (
+ {
+ desc => 'title shown for bromley problem on main site',
+ host => 'http://www.fixmystreet.com',
+ extra => [
+ {
+ name => 'fms_extra_title',
+ value => 'Mr',
+ description => 'FMS_EXTRA_TITLE',
+ },
+ ],
+ },
+ {
+ desc =>
+ 'title, first and last name shown for bromley problem on cobrand',
+ host => 'http://bromley.fixmystreet.com',
+ first_name => 'Test',
+ last_name => 'User',
+ extra => [
+ {
+ name => 'fms_extra_title',
+ value => 'Mr',
+ description => 'FMS_EXTRA_TITLE',
+ },
+ {
+ name => 'first_name',
+ value => 'Test',
+ description => 'FIRST_NAME',
+ },
+ {
+ name => 'last_name',
+ value => 'User',
+ description => 'LAST_NAME',
+ },
+ ],
+ },
+ )
+{
+ subtest $test->{desc} => sub {
+ $mech->host( $test->{host} );
+
+ $mech->log_out_ok;
+
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => 'BR1 3UH', } },
+ "submit location" );
+ $mech->follow_link_ok(
+ { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link"
+ );
+
+ my $fields = $mech->visible_form_values('mapSkippedForm');
+ ok exists( $fields->{fms_extra_title} ), 'user title field displayed';
+ if ( $test->{first_name} ) {
+ ok exists( $fields->{first_name} ), 'first name field displayed';
+ ok exists( $fields->{last_name} ), 'last name field displayed';
+ ok !exists( $fields->{name} ), 'no name field displayed';
+ }
+ else {
+ ok !exists( $fields->{first_name} ),
+ 'first name field not displayed';
+ ok !exists( $fields->{last_name} ), 'last name field not displayed';
+ ok exists( $fields->{name} ), 'name field displayed';
+ }
+
+ my $submission_fields = {
+ title => "Test Report",
+ detail => 'Test report details.',
+ photo => '',
+ email => 'firstlast@example.com',
+ fms_extra_title => 'Mr',
+ may_show_name => '1',
+ phone => '07903 123 456',
+ category => 'Trees',
+ password_register => '',
+ };
+
+ if ( $test->{first_name} ) {
+ $submission_fields->{first_name} = $test->{first_name};
+ $submission_fields->{last_name} = $test->{last_name};
+ }
+ else {
+ $submission_fields->{name} = 'Test User';
+ }
+
+ $mech->submit_form_ok( { with_fields => $submission_fields },
+ "submit good details" );
+
+ my $user =
+ FixMyStreet::App->model('DB::User')
+ ->find( { email => 'firstlast@example.com' } );
+
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+ my $extras = $report->extra;
+ is_deeply $extras, $test->{extra}, 'extra contains correct values';
+
+ $user->problems->delete;
+ $user->delete;
+ };
+}
+
$contact1->delete;
$contact2->delete;
$contact3->delete;
diff --git a/t/open311.t b/t/open311.t
index 30de330b6..83b81d8aa 100644
--- a/t/open311.t
+++ b/t/open311.t
@@ -5,6 +5,9 @@ use warnings;
use Test::More;
use Test::Warn;
use FixMyStreet::App;
+use CGI::Simple;
+use HTTP::Response;
+use DateTime;
use FindBin;
use lib "$FindBin::Bin/../perllib";
@@ -39,4 +42,318 @@ my $expected_error = qr{.*request failed: 500 Can.t connect to 192.168.50.1:80 \
warning_like {$o2->send_service_request( $p, { url => 'http://example.com/' }, 1 )} $expected_error, 'warning generated on failed call';
+my $dt = DateTime->now();
+
+my $user = FixMyStreet::App->model('DB::User')->new( {
+ name => 'Test User',
+ email => 'test@example.com',
+} );
+
+my $problem = FixMyStreet::App->model('DB::Problem')->new( {
+ id => 80,
+ external_id => 81,
+ state => 'confirmed',
+ title => 'a problem',
+ detail => 'problem detail',
+ category => 'pothole',
+ latitude => 1,
+ longitude => 2,
+ user => $user,
+} );
+
+subtest 'posting service request' => sub {
+ my $extra = {
+ url => 'http://example.com/report/1',
+ };
+
+ my $results = make_service_req( $problem, $extra, $problem->category, '<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id>248</service_request_id></request></service_requests>' );
+
+ is $results->{ res }, 248, 'got request id';
+
+ my $req = $o->test_req_used;
+
+ my $description = <<EOT;
+title: a problem
+
+detail: problem detail
+
+url: http://example.com/report/1
+
+Submitted via FixMyStreet
+EOT
+;
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+
+ is $c->param('email'), $user->email, 'correct email';
+ is $c->param('first_name'), 'Test', 'correct first name';
+ is $c->param('last_name'), 'User', 'correct last name';
+ is $c->param('lat'), 1, 'latitide correct';
+ is $c->param('long'), 2, 'longitude correct';
+ is $c->param('description'), $description, 'descritpion correct';
+ is $c->param('service_code'), 'pothole', 'service code correct';
+};
+
+for my $test (
+ {
+ desc => 'extra values in service request',
+ extra => [
+ {
+ name => 'title',
+ value => 'A title',
+ }
+ ],
+ params => [
+ [ 'attribute[title]', 'A title', 'extra paramater used correctly' ]
+ ]
+ },
+ {
+ desc => 'first and last names in extra used correctly',
+ extra => [
+ {
+ name => 'first_name',
+ value => 'First',
+ },
+ {
+ name => 'last_name',
+ value => 'Last',
+ },
+ ],
+ params => [
+ [ 'first_name', 'First', 'first name correct' ],
+ [ 'last_name', 'Last', 'last name correct' ],
+ [ 'attribute[first_name]', undef, 'no first_name attribute param' ],
+ [ 'attribute[last_name]', undef, 'no last_name attribute param' ],
+ ],
+ },
+ {
+ title => 'magic fms_extra parameters handled correctly',
+ extra => [
+ {
+ name => 'fms_extra_title',
+ value => 'Extra title',
+ }
+ ],
+ params => [
+ [
+ 'attribute[title]',
+ 'Extra title',
+ 'fms_extra extra param used correctly'
+ ]
+ ],
+ },
+ )
+{
+ subtest $test->{desc} => sub {
+ $problem->extra( $test->{extra} );
+
+ my $extra = { url => 'http://example.com/report/1', };
+
+ my $results = make_service_req( $problem, $extra, $problem->category,
+'<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id>248</service_request_id></request></service_requests>'
+ );
+ my $req = $o->test_req_used;
+ my $c = CGI::Simple->new( $results->{req}->content );
+
+ for my $param ( @{ $test->{params} } ) {
+ is $c->param( $param->[0] ), $param->[1], $param->[2];
+ }
+ };
+}
+
+my $comment = FixMyStreet::App->model('DB::Comment')->new( {
+ id => 38362,
+ user => $user,
+ problem => $problem,
+ anonymous => 0,
+ text => 'this is a comment',
+ confirmed => $dt,
+ extra => { title => 'Mr', email_alerts_requested => 0 },
+} );
+
+subtest 'basic request update post parameters' => sub {
+ my $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>' );
+
+ is $results->{ res }, 248, 'got update id';
+
+ my $req = $o->test_req_used;
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+
+ is $c->param('description'), 'this is a comment', 'email correct';
+ is $c->param('email'), 'test@example.com', 'email correct';
+ is $c->param('status'), 'OPEN', 'status correct';
+ is $c->param('service_request_id_ext'), 80, 'external request id correct';
+ is $c->param('service_request_id'), 81, 'request id correct';
+ is $c->param('public_anonymity_required'), 'FALSE', 'anon status correct';
+ is $c->param('updated_datetime'), $dt, 'correct date';
+ is $c->param('title'), 'Mr', 'correct title';
+ is $c->param('last_name'), 'User', 'correct first name';
+ is $c->param('first_name'), 'Test', 'correct second name';
+ is $c->param('email_alerts_requested'), 'FALSE', 'email alerts flag correct';
+};
+
+foreach my $test (
+ {
+ desc => 'comment with fixed state sends status of CLOSED',
+ state => 'fixed',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with fixed - user state sends status of CLOSED',
+ state => 'fixed - user',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with fixed - council state sends status of CLOSED',
+ state => 'fixed - council',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with closed state sends status of CLOSED',
+ state => 'closed',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with investigating state sends status of OPEN',
+ state => 'investigating',
+ anon => 0,
+ status => 'OPEN',
+ },
+ {
+ desc => 'comment with planned state sends status of OPEN',
+ state => 'planned',
+ anon => 0,
+ status => 'OPEN',
+ },
+ {
+ desc => 'comment with in progress state sends status of OPEN',
+ state => 'in progress',
+ anon => 0,
+ status => 'OPEN',
+ },
+ {
+ desc => 'anonymous commment sets public_anonymity_required to true',
+ state => 'confirmed',
+ anon => 1,
+ status => 'OPEN',
+ },
+) {
+ subtest $test->{desc} => sub {
+ $comment->problem->state( $test->{state} );
+ $comment->anonymous( $test->{anon} );
+
+ my $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>' );
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+ is $c->param('status'), $test->{status}, 'correct status';
+ is $c->param('public_anonymity_required'), $test->{anon} ? 'TRUE' : 'FALSE', 'correct anonymity';
+ };
+}
+
+
+for my $test (
+ {
+ desc => 'update name name taken from comment over user',
+ comment_name => 'First Last',
+ user_name => 'Personal Family',
+ extra => undef,
+ first_name => 'First',
+ last_name => 'Last'
+ },
+ {
+ desc => 'update name name taken from user if no comment name',
+ comment_name => '',
+ user_name => 'Personal Family',
+ extra => undef,
+ first_name => 'Personal',
+ last_name => 'Family'
+ },
+ {
+ desc => 'update name taken from extra if available',
+ comment_name => 'First Last',
+ user_name => 'Personal Family',
+ extra => { first_name => 'Forename', last_name => 'Surname' },
+ first_name => 'Forename',
+ last_name => 'Surname'
+ },
+ )
+{
+ subtest $test->{desc} => sub {
+ $comment->name( $test->{comment_name} );
+ $user->name( $test->{user_name} );
+ $comment->extra( $test->{ extra } );
+
+ my $results = make_update_req( $comment,
+'<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>'
+ );
+
+ my $c = CGI::Simple->new( $results->{req}->content );
+ is $c->param('first_name'), $test->{first_name}, 'first name correct';
+ is $c->param('last_name'), $test->{last_name}, 'last name correct';
+ };
+}
+
+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';
+
+ is $results->{ res }, 0, 'No update_id is a failure';
+};
+
+subtest 'error reponse' => 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';
+
+ is $results->{ res }, 0, 'error in response is a failure';
+};
+
done_testing();
+
+sub make_update_req {
+ my $comment = shift;
+ my $xml = shift;
+
+ return make_req( $comment, $xml, 'post_service_request_update', 'update.xml' );
+}
+
+sub make_service_req {
+ my $problem = shift;
+ my $extra = shift;
+ my $service_code = shift;
+ my $xml = shift;
+
+ return make_req( $problem, $xml, 'send_service_request', 'requests.xml', $extra, $service_code );
+}
+
+sub make_req {
+ my $object = shift;
+ my $xml = shift;
+ my $method = shift;
+ my $path = shift;
+ my @args = @_;
+
+ my $o =
+ Open311->new( test_mode => 1, end_point => 'http://localhost/o311' );
+
+ my $test_res = HTTP::Response->new();
+ $test_res->code(200);
+ $test_res->message('OK');
+ $test_res->content($xml);
+
+ $o->test_get_returns( { $path => $test_res } );
+
+ my $res = $o->$method($object, @args);
+
+ my $req = $o->test_req_used;
+
+ return { res => $res, req => $req };
+}
diff --git a/t/open311/getservicerequestupdates.t b/t/open311/getservicerequestupdates.t
new file mode 100644
index 000000000..063d7e378
--- /dev/null
+++ b/t/open311/getservicerequestupdates.t
@@ -0,0 +1,409 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use Test::More;
+use CGI::Simple;
+
+use FindBin;
+use lib "$FindBin::Bin/../perllib";
+use lib "$FindBin::Bin/../commonlib/perllib";
+
+use_ok( 'Open311' );
+
+use_ok( 'Open311::GetServiceRequestUpdates' );
+use DateTime;
+use FixMyStreet::App;
+
+my $user = FixMyStreet::App->model('DB::User')->find_or_create(
+ {
+ email => 'system_user@example.com'
+ }
+);
+
+my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+<service_requests_updates>
+<request_update>
+<update_id>638344</update_id>
+<service_request_id>1</service_request_id>
+<service_request_id_ext>1</service_request_id_ext>
+<status>open</status>
+<description>This is a note</description>
+UPDATED_DATETIME
+</request_update>
+</service_requests_updates>
+};
+
+
+my $dt = DateTime->now;
+
+# basic xml -> perl object tests
+for my $test (
+ {
+ desc => 'basic parsing - element missing',
+ updated_datetime => '',
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note' },
+ },
+ {
+ desc => 'basic parsing - empty element',
+ updated_datetime => '<updated_datetime />',
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note', updated_datetime => {} } ,
+ },
+ {
+ desc => 'basic parsing - element with no content',
+ updated_datetime => '<updated_datetime></updated_datetime>',
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note', updated_datetime => {} } ,
+ },
+ {
+ desc => 'basic parsing - element with content',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note', updated_datetime => $dt } ,
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $local_requests_xml = $requests_xml;
+ $local_requests_xml =~ s/UPDATED_DATETIME/$test->{updated_datetime}/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ my $res = $o->get_service_request_updates;
+ is_deeply $res->[0], $test->{ res }, 'result looks correct';
+
+ };
+}
+
+my $problem_rs = FixMyStreet::App->model('DB::Problem');
+my $problem = $problem_rs->new(
+ {
+ postcode => 'EH99 1SP',
+ latitude => 1,
+ longitude => 1,
+ areas => 1,
+ title => '',
+ detail => '',
+ used_map => 1,
+ user_id => 1,
+ name => '',
+ state => 'confirmed',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ user => $user,
+ created => DateTime->now()->subtract( days => 1 ),
+ lastupdate => DateTime->now()->subtract( days => 1 ),
+ anonymous => 1,
+ external_id => time(),
+ council => 2482,
+ }
+);
+
+$problem->insert;
+
+for my $test (
+ {
+ desc => 'element with content',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'confirmed',
+ close_comment => 0,
+ mark_fixed=> 0,
+ mark_open => 0,
+ end_state => 'confirmed',
+ },
+ {
+ desc => 'comment closes report',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'confirmed',
+ close_comment => 1,
+ mark_fixed=> 1,
+ mark_open => 0,
+ end_state => 'fixed - council',
+ },
+ {
+ desc => 'comment re-opens fixed report',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'fixed - user',
+ close_comment => 0,
+ mark_fixed => 0,
+ mark_open => 1,
+ end_state => 'confirmed',
+ },
+ {
+ desc => 'comment re-opens closed report',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'closed',
+ close_comment => 0,
+ mark_fixed => 0,
+ mark_open => 1,
+ end_state => 'confirmed',
+ },
+ {
+ desc => 'comment leaves report closed',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'closed',
+ close_comment => 1,
+ mark_fixed => 0,
+ mark_open => 0,
+ end_state => 'closed',
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $local_requests_xml = $requests_xml;
+ $local_requests_xml =~ s/UPDATED_DATETIME/$test->{updated_datetime}/;
+ $local_requests_xml =~ s#<service_request_id>\d+</service_request_id>#<service_request_id>@{[$problem->external_id]}</service_request_id>#;
+ $local_requests_xml =~ s#<service_request_id_ext>\d+</service_request_id_ext>#<service_request_id_ext>@{[$problem->id]}</service_request_id_ext>#;
+ $local_requests_xml =~ s#<status>\w+</status>#<status>closed</status># if $test->{close_comment};
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ $problem->comments->delete;
+ $problem->state( $test->{start_state} );
+ $problem->update;
+
+ my $council_details = { areaid => 2482 };
+ my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
+ $update->update_comments( $o, $council_details );
+
+ is $problem->comments->count, 1, 'comment count';
+ $problem->discard_changes;
+
+ my $c = FixMyStreet::App->model('DB::Comment')->search( { external_id => $test->{external_id} } )->first;
+ ok $c, 'comment exists';
+ is $c->text, $test->{description}, 'text correct';
+ is $c->mark_fixed, $test->{mark_fixed}, 'mark_closed correct';
+ is $c->mark_open, $test->{mark_open}, 'mark_open correct';
+ is $problem->state, $test->{end_state}, 'correct problem state';
+ };
+}
+
+
+foreach my $test (
+ {
+ desc => 'date for comment correct',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ external_id => 638344,
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $dt = DateTime->now();
+ $dt->subtract( minutes => 10 );
+ my $local_requests_xml = $requests_xml;
+
+ my $updated = sprintf( '<updated_datetime>%s</updated_datetime>', $dt );
+ $local_requests_xml =~ s/UPDATED_DATETIME/$updated/;
+ $local_requests_xml =~ s#<service_request_id>\d+</service_request_id>#<service_request_id>@{[$problem->external_id]}</service_request_id>#;
+ $local_requests_xml =~ s#<service_request_id_ext>\d+</service_request_id_ext>#<service_request_id_ext>@{[$problem->id]}</service_request_id_ext>#;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ $problem->comments->delete;
+
+ my $council_details = { areaid => 2482 };
+ my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
+ $update->update_comments( $o, $council_details );
+
+ my $comment = $problem->comments->first;
+ is $comment->created, $dt, 'created date set to date from XML';
+ is $comment->confirmed, $dt, 'confirmed date set to date from XML';
+ };
+}
+
+my $problem2 = $problem_rs->new(
+ {
+ postcode => 'EH99 1SP',
+ latitude => 1,
+ longitude => 1,
+ areas => 1,
+ title => '',
+ detail => '',
+ used_map => 1,
+ user_id => 1,
+ name => '',
+ state => 'confirmed',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ user => $user,
+ created => DateTime->now(),
+ lastupdate => DateTime->now(),
+ anonymous => 1,
+ external_id => $problem->external_id,
+ council => 2651,
+ }
+);
+
+$problem2->insert();
+$problem->comments->delete;
+$problem2->comments->delete;
+
+for my $test (
+ {
+ desc => 'identical external_ids on problem resolved using council',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ external_id => 638344,
+ area_id => 2651,
+ request_id => $problem2->external_id,
+ request_id_ext => $problem2->id,
+ p1_comments => 0,
+ p2_comments => 1,
+ },
+ {
+ desc => 'identical external_ids on comments resolved',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ external_id => 638344,
+ area_id => 2482,
+ request_id => $problem->external_id,
+ request_id_ext => $problem->id,
+ p1_comments => 1,
+ p2_comments => 1,
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $local_requests_xml = $requests_xml;
+ $local_requests_xml =~ s/UPDATED_DATETIME/$test->{updated_datetime}/;
+ $local_requests_xml =~ s#<service_request_id>\d+</service_request_id>#<service_request_id>$test->{request_id}</service_request_id>#;
+ $local_requests_xml =~ s#<service_request_id_ext>\d+</service_request_id_ext>#<service_request_id_ext>$test->{request_id_ext}</service_request_id_ext>#;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+
+ my $council_details = { areaid => $test->{area_id} };
+ my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
+ $update->update_comments( $o, $council_details );
+
+ is $problem->comments->count, $test->{p1_comments}, 'comment count for first problem';
+ is $problem2->comments->count, $test->{p2_comments}, 'comment count for second problem';
+ };
+}
+
+subtest 'using start and end date' => sub {
+ my $local_requests_xml = $requests_xml;
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ my $start_dt = DateTime->now();
+ $start_dt->subtract( days => 1 );
+ my $end_dt = DateTime->now();
+
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ start_date => $start_dt,
+ );
+
+ my $res = $update->update_comments( $o );
+ is $res, 0, 'returns 0 if start but no end date';
+
+ $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ end_date => $end_dt,
+ );
+
+ $res = $update->update_comments( $o );
+ is $res, 0, 'returns 0 if end but no start date';
+
+ $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ start_date => $start_dt,
+ end_date => $end_dt,
+ );
+
+ my $council_details = { areaid => 2482 };
+ $update->update_comments( $o, $council_details );
+
+ my $start = $start_dt . '';
+ my $end = $end_dt . '';
+
+ my $uri = URI->new( $o->test_uri_used );
+ my $c = CGI::Simple->new( $uri->query );
+
+ is $c->param('start_date'), $start, 'start date used';
+ is $c->param('end_date'), $end, 'end date used';
+};
+
+subtest 'check that existing comments are not duplicated' => sub {
+ my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests_updates>
+ <request_update>
+ <update_id>638344</update_id>
+ <service_request_id>@{[ $problem->external_id ]}</service_request_id>
+ <service_request_id_ext>@{[ $problem->id ]}</service_request_id_ext>
+ <status>open</status>
+ <description>This is a note</description>
+ <updated_datetime>UPDATED_DATETIME</updated_datetime>
+ </request_update>
+ <request_update>
+ <update_id>638354</update_id>
+ <service_request_id>@{[ $problem->external_id ]}</service_request_id>
+ <service_request_id_ext>@{[ $problem->id ]}</service_request_id_ext>
+ <status>open</status>
+ <description>This is a different note</description>
+ <updated_datetime>UPDATED_DATETIME2</updated_datetime>
+ </request_update>
+ </service_requests_updates>
+ };
+
+ $problem->comments->delete;
+
+ my $comment = FixMyStreet::App->model('DB::Comment')->new(
+ {
+ problem => $problem,
+ external_id => 638344,
+ text => 'This is a note',
+ user => $user,
+ state => 'confirmed',
+ mark_fixed => 0,
+ anonymous => 0,
+ confirmed => $dt,
+ }
+ );
+ $comment->insert;
+
+ is $problem->comments->count, 1, 'one comment before fetching updates';
+
+ $requests_xml =~ s/UPDATED_DATETIME2/$dt/;
+ $requests_xml =~ s/UPDATED_DATETIME/@{[ $comment->confirmed ]}/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ );
+
+ my $council_details = { areaid => 2482 };
+ $update->update_comments( $o, $council_details );
+
+ $problem->discard_changes;
+ is $problem->comments->count, 2, 'two comments after fetching updates';
+
+ $update->update_comments( $o, $council_details );
+ $problem->discard_changes;
+ is $problem->comments->count, 2, 're-fetching updates does not add comments';
+
+ $problem->comments->delete;
+ $update->update_comments( $o, $council_details );
+ $problem->discard_changes;
+ is $problem->comments->count, 2, 'if comments are deleted then they are added';
+};
+
+$problem2->comments->delete();
+$problem->comments->delete();
+$problem2->delete;
+$problem->delete;
+$user->comments->delete;
+$user->problems->delete;
+$user->delete;
+
+done_testing();
diff --git a/t/open311/populate-service-list.t b/t/open311/populate-service-list.t
index bdb7404f9..63500d6cb 100644
--- a/t/open311/populate-service-list.t
+++ b/t/open311/populate-service-list.t
@@ -203,6 +203,304 @@ subtest 'check conflicting contacts not changed' => sub {
is $contact_count, 4, 'correct number of contacts';
};
+subtest 'check meta data population' => sub {
+ my $processor = Open311::PopulateServiceList->new( council_list => [] );
+
+ my $meta_xml = '<?xml version="1.0" encoding="utf-8"?>
+<service_definition>
+ <service_code>100</service_code>
+ <attributes>
+ <attribute>
+ <variable>true</variable>
+ <code>type</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ </attributes>
+</service_definition>
+ ';
+
+ my $contact = FixMyStreet::App->model('DB::Contact')->find_or_create(
+ {
+ area_id => 1,
+ email => '001',
+ category => 'Bins left out 24x7',
+ confirmed => 1,
+ deleted => 0,
+ editor => $0,
+ whenedited => \'ms_current_timestamp()',
+ note => 'test contact',
+ }
+ );
+
+ my $o = Open311->new(
+ jurisdiction => 'mysociety',
+ endpoint => 'http://example.com',
+ test_mode => 1,
+ test_get_returns => { 'services/100.xml' => $meta_xml }
+ );
+
+ my $council = FixMyStreet::App->model('DB::Open311conf')->new( {
+ area_id => 2482
+ } );
+
+ $processor->_current_open311( $o );
+ $processor->_current_council( $council );
+ $processor->_current_service( { service_code => 100 } );
+
+ $processor->_add_contact_to_meta( $contact );
+
+ my $extra = [ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ } ];
+
+ $contact->discard_changes;
+
+ is_deeply $contact->extra, $extra, 'meta data saved';
+};
+
+subtest 'check attribute ordering' => sub {
+ my $processor = Open311::PopulateServiceList->new( council_list => [] );
+
+ my $meta_xml = '<?xml version="1.0" encoding="utf-8"?>
+<service_definition>
+ <service_code>100</service_code>
+ <attributes>
+ <attribute>
+ <variable>true</variable>
+ <code>type</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ <attribute>
+ <variable>true</variable>
+ <code>colour</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Colour of bin</datatype_description>
+ <order>3</order>
+ <description>Colour of bin</description>
+ </attribute>
+ <attribute>
+ <variable>true</variable>
+ <code>size</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Size of bin</datatype_description>
+ <order>2</order>
+ <description>Size of bin</description>
+ </attribute>
+ </attributes>
+</service_definition>
+ ';
+
+ my $contact = FixMyStreet::App->model('DB::Contact')->find_or_create(
+ {
+ area_id => 1,
+ email => '001',
+ category => 'Bins left out 24x7',
+ confirmed => 1,
+ deleted => 0,
+ editor => $0,
+ whenedited => \'ms_current_timestamp()',
+ note => 'test contact',
+ }
+ );
+
+ my $o = Open311->new(
+ jurisdiction => 'mysociety',
+ endpoint => 'http://example.com',
+ test_mode => 1,
+ test_get_returns => { 'services/100.xml' => $meta_xml }
+ );
+
+ my $council = FixMyStreet::App->model('DB::Open311conf')->new( {
+ area_id => 1
+ } );
+
+ $processor->_current_open311( $o );
+ $processor->_current_council( $council );
+ $processor->_current_service( { service_code => 100 } );
+
+ $processor->_add_contact_to_meta( $contact );
+
+ my $extra = [
+ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'size',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Size of bin',
+ order => 2,
+ description => 'Size of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'colour',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Colour of bin',
+ order => 3,
+ description => 'Colour of bin'
+
+ },
+ ];
+
+ $contact->discard_changes;
+
+ is_deeply $contact->extra, $extra, 'meta data re-ordered correctly';
+};
+
+subtest 'check bromely skip code' => sub {
+ my $processor = Open311::PopulateServiceList->new( council_list => [] );
+
+ my $meta_xml = '<?xml version="1.0" encoding="utf-8"?>
+<service_definition>
+ <service_code>100</service_code>
+ <attributes>
+ <attribute>
+ <variable>true</variable>
+ <code>type</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ <attribute>
+ <variable>true</variable>
+ <code>title</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ <attribute>
+ <variable>true</variable>
+ <code>report_url</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ </attributes>
+</service_definition>
+ ';
+
+ my $contact = FixMyStreet::App->model('DB::Contact')->find_or_create(
+ {
+ area_id => 1,
+ email => '001',
+ category => 'Bins left out 24x7',
+ confirmed => 1,
+ deleted => 0,
+ editor => $0,
+ whenedited => \'ms_current_timestamp()',
+ note => 'test contact',
+ }
+ );
+
+ my $o = Open311->new(
+ jurisdiction => 'mysociety',
+ endpoint => 'http://example.com',
+ test_mode => 1,
+ test_get_returns => { 'services/100.xml' => $meta_xml }
+ );
+
+ my $council = FixMyStreet::App->model('DB::Open311conf')->new( {
+ area_id => 2482
+ } );
+
+ $processor->_current_open311( $o );
+ $processor->_current_council( $council );
+ $processor->_current_service( { service_code => 100 } );
+
+ $processor->_add_contact_to_meta( $contact );
+
+ my $extra = [ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ } ];
+
+ $contact->discard_changes;
+
+ is_deeply $contact->extra, $extra, 'only non std bromley meta data saved';
+
+ $council->area_id(1);
+
+ $processor->_current_council( $council );
+ $processor->_add_contact_to_meta( $contact );
+
+ $extra = [
+ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'title',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'report_url',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ ];
+
+ $contact->discard_changes;
+
+ is_deeply $contact->extra, $extra, 'all meta data saved for non bromley';
+};
+
sub get_standard_xml {
return qq{<?xml version="1.0" encoding="utf-8"?>
<services>
diff --git a/templates/web/bromley/footer.html b/templates/web/bromley/footer.html
index 9be0741bf..4ef3011a9 100644
--- a/templates/web/bromley/footer.html
+++ b/templates/web/bromley/footer.html
@@ -1,22 +1,3 @@
- [% IF pagefooter %]
- <footer role="content-info">
- <div class="tablewrapper bordered">
- <div id="footer-mobileapps">
- <h4>Mobile apps</h4>
-
- <ul>
- <li><a class="m-app-iphone" href="http://itunes.apple.com/gb/app/fixmystreet/id297456545">iPhone</a></li>
- <li><a class="m-app-droid" href="https://market.android.com/details?id=com.android.fixmystreet">Android</a></li>
- <li><a class="m-app-nokia" href="http://store.ovi.com/content/107557">Nokia</a></li>
- <li><a class="m-app-iphone-streetreport" href="http://itunes.apple.com/gb/app/streetreport/id371891859">iPhone Street Report</a></li>
- </ul>
- </div>
-
- <div id="footer-help">
- </div>
- </div>
- </footer>
- [% END %]
</div><!-- .content role=main -->
</div><!-- .container -->
</div><!-- .table-cell -->
@@ -25,9 +6,8 @@
<div class="nav-wrapper-2">
<div id="main-nav" role="navigation">
<ul id="mysoc-menu">
- <li><a href="http://www.fixmystreet.com/">Powered by FixMyStreet</a></li>
+ <li><a href="http://www.fixmystreet.com/">Powered by <img src="/cobrands/bromley/fms-logo.png" style="height:20px;"></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>[%
@@ -44,7 +24,21 @@
</div>
</div>
-<!-- [% INCLUDE 'debug_footer.html' %] -->
</div> <!-- .wrapper -->
+
+<div id="bromley-footer" class="desk-only">
+ <p class="copy">&copy; 2012 London Borough of Bromley</p>
+
+ <a href="http://www.direct.gov.uk/"><img src="http://www.bromley.gov.uk/site/images/directgov.jpg" alt="Directgov website link - Public services all in one place" /></a>
+
+ <ul class="footer-nav">
+ <li><a href="#bromley-header">To the top</a></li>
+ <li><a href="http://www.bromley.gov.uk/terms">Disclaimer</a></li>
+ <li><a href="http://www.bromley.gov.uk/privacy" rel="nofollow">Privacy and cookies</a></li>
+ <li><a href="http://www.bromley.gov.uk/accesstoinfo">Access to information</a></li>
+ </ul>
+
+</div>
+
</body>
</html>
diff --git a/templates/web/bromley/header.html b/templates/web/bromley/header.html
index f7beabd8c..d1fa64273 100644
--- a/templates/web/bromley/header.html
+++ b/templates/web/bromley/header.html
@@ -6,31 +6,75 @@
<!--[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">
<link rel="stylesheet" href="[% version('/cobrands/bromley/base.css') %]">
- <!-- <link rel="stylesheet" href="[% version('/cobrands/fixmystreet/layout.css') %]" media="(min-width:48em)"> -->
+ <link rel="stylesheet" href="[% version('/cobrands/bromley/layout.css') %]" media="(min-width:48em)">
<link rel="stylesheet" href="[% version('/js/fancybox/jquery.fancybox-1.3.4.css') %]">
+ <link rel="stylesheet" href="[% version('/cobrands/bromley/bromley.css') %]">
<!--[if (lt IE 9) & (!IEMobile)]>
- <!-- <link rel="stylesheet" href="[% version('/cobrands/fixmystreet/layout.css') %]"> -->
+ <link rel="stylesheet" href="[% version('/cobrands/bromley/layout.css') %]">
<![endif]-->
- <script src="[% version('/js/modernizr.custom.76759.js') %]" charset="utf-8"></script>
+ <script src="[% version('/js/modernizr.custom.js') %]" charset="utf-8"></script>
[% INCLUDE 'common_header_tags.html', js_override = '/cobrands/fixmystreet/fixmystreet.js' %]
<script src="[% version('/js/fancybox/jquery.fancybox-1.3.4.pack.js') %]" charset="utf-8"></script>
- [% 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' %]
+ <link rel="Shortcut Icon" type="image/x-icon" href="/cobrands/bromley/favicon.ico">
</head>
<body class="[% bodyclass | html IF bodyclass %]">
+<div id="bromley-header" class="desk-only">
+ <ul class="header-nav">
+ <li><a href="http://www.bromley.gov.uk/accessibility">Accessibility</a></li>
+ <li><a class="skiplink" href="http://www.bromley.gov.uk/#user-meta" rel="nofollow">Skip to content</a></li>
+ <!-- <li><a rel="nofollow" href="http://www.bromley.gov.uk/a_to_z?previewstyle=generic/print.css">Printer friendly</a></li> -->
+ <!-- <li><a href="http://www.bromley.gov.uk/accessibility/settings">Text size: AAA</a></li> -->
+ <li><div id="google_translate_element"></div></li>
+ </ul>
+
+ <div class="logo">
+ <a href="http://www.bromley.gov.uk"><img src="/cobrands/bromley/bromley-logo.jpg" alt="London Borough of Bromley logo" width="159" height="114" style="width:159px; height:114px;" /></a>
+ </div>
+
+ <!-- <div class="sign-in">
+ <p>
+ You are not signed in. <a href="https://www.bromley.gov.uk/sign_in?referer=%2fa_to_z">Sign in</a>
+ or <a href="https://www.bromley.gov.uk/register">register</a>?
+ </p>
+ </div> -->
+
+ <div class="main-menu">
+ <ul>
+ <li class="home"><a href="http://www.bromley.gov.uk">Home</a></li>
+ <li><a href="http://www.bromley.gov.uk/a_to_z">A to Z</a></li>
+ <li><a href="http://www.bromley.gov.uk/site_map">Site map</a></li>
+ </ul>
+ <form action="http://www.bromley.gov.uk/site/scripts/google_results.aspx" method="get" id="search">
+ <label for="SearchSite">Search by Keyword</label>
+ <input type="text" size="18" maxlength="40" class="field" name="q" id="SearchSite" value="Search by keyword" onclick="if (this.value == 'Search by keyword') { this.value = ''; }" onblur="if (this.value == '') { this.value = 'Search by keyword'; }" />
+ <input value="Search" id="SearchSubmit" type="submit" class="button" />
+ </form>
+ </div>
+
+ <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/Bromley' %]span[% ELSE %]a href="/reports/Bromley"[% 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 class="wrapper">
<div class="table-cell">
<header id="site-header" role="banner">
@@ -51,6 +95,8 @@
[% END %]
</div>
+ [% pre_container_extra %]
+
<div class="container">
<div class="content[% " $mainclass" | html IF mainclass %]" role="main">
diff --git a/templates/web/bromley/index.html b/templates/web/bromley/index.html
new file mode 100644
index 000000000..94807431f
--- /dev/null
+++ b/templates/web/bromley/index.html
@@ -0,0 +1,110 @@
+[%# Assumes fixmystreet cobrand is using FMS map template - for bonus points preload all the right map elements. %]
+[% map_js = BLOCK %]
+<script>
+yepnope.addPrefix( 'preload', function ( resource ) {
+ resource.noexec = true;
+ return resource;
+});
+Modernizr.load({
+ load: [
+ "preload![% version('/js/OpenLayers.fixmystreet.js') %]",
+ "preload![% version('/js/map-OpenLayers.js') %]",
+ "preload![% version('/js/map-bing-ol.js') %]",
+ "preload![% version('/js/jquery.ba-hashchange.min.js') %]"
+ ]
+});
+</script>
+[% END %]
+
+[% pre_container_extra = BLOCK %]
+<div id="front-main">
+ <div id="front-main-container">
+ <h1>Reporting a problem in Bromley&rsquo;s streets or parks</h1>
+
+ [%
+ question
+ = c.cobrand.enter_postcode_text()
+ || loc("Enter a nearby GB postcode, or street name and area");
+ %]
+
+ <form action="[% c.uri_for('/around') %]" method="get" name="postcodeForm" id="postcodeForm">
+ <label for="pc">Enter a London Borough of Bromley postcode, or street name and area:</label>
+ <div>
+ <input type="text" name="pc" value="" id="pc" size="10" maxlength="200" placeholder="[% tprintf(loc('e.g. ‘%s’ or ‘%s’'), c.cobrand.example_places) %]">
+ <input type="submit" value="[% loc('Go') %]" id="submit">
+ </div>
+ </form>
+
+ <p>This is primarily for reporting physical problems that can be fixed
+ like graffiti, fly tipping, or broken paving slabs to report other
+ kinds of problems like missed bins use our
+ <a href="http://www.bromley.gov.uk/report">online report it forms</a>.
+ </p>
+
+ </div>
+</div>
+[% END %]
+
+[% INCLUDE 'header.html', title => '' , bodyclass => 'frontpage fullwidthpage' %]
+
+[% IF error %]
+ <p class="error">[% error %]</p>
+[% END %]
+
+<div class="tablewrapper">
+ <div id="front-howto">
+ <h2>[% loc('How to report a problem') %]</h2>
+
+ <ol class="big-numbers">
+ <li>[% question %]</li>
+ <li>[% loc('Locate the problem on a map of the area') %]</li>
+ <li>[% loc('Enter details of the problem') %]</li>
+ <li>It gets sent to the council</li>
+ </ol>
+
+ <section class="full-width">
+ [% INCLUDE "front/stats.html" %]
+ [% TRY %][% INCLUDE "front/tips.html" %][% CATCH file %][% END %]
+ </section>
+ </div>
+
+
+ [%
+ recent_photos = c.cobrand.recent_photos(5);
+ %]
+
+ [% IF recent_photos.size %]
+ <div id="front-recently">
+ <h2>[% loc('Recently reported problems') %]</h2>
+
+ <section class="full-width">
+ <ul class="issue-list-a">
+ [% FOREACH p IN recent_photos %]
+ <li>
+ <a href="/report/[% p.id %]">
+ <div class="text">
+ <h4>[% p.title | html %]</h4>
+ <small>[% prettify_epoch( p.confirmed_local.epoch, 1 ) %]</small>
+ </div>
+ <div class="img">
+ <img alt="[% p.title | html %]" title="[% p.title | html %]" height="60" width="90" src="/photo/[% p.id %].fp.jpeg">
+ </div>
+ </a>
+ </li>
+ [% END %]
+ </ul>
+ </section>
+
+ <p id="bromley-powered-by" class="desk-only">
+ <a href="http://www.fixmystreet.com/">Powered by <img src="/cobrands/bromley/fms-logo.png" style="height:20px;"></a>
+ </p>
+
+ </div>
+ [% END %]
+</div>
+
+
+<!-- [% TRY %][% INCLUDE 'front/news.html' %][% CATCH file %][% END %] -->
+
+
+[% INCLUDE 'footer.html' pagefooter = 'yes' %]
diff --git a/templates/web/bromley/report/display.html b/templates/web/bromley/report/display.html
new file mode 100644
index 000000000..ad06f923b
--- /dev/null
+++ b/templates/web/bromley/report/display.html
@@ -0,0 +1,209 @@
+[%
+ PROCESS "maps/${map.type}.html";
+
+ problem_title = problem.title _ ' - ' _ loc('Viewing a problem');
+ INCLUDE 'header.html'
+ title = problem_title
+ rss = [ loc('Updates to this problem, FixMyStreet'), "/rss/$problem.id" ]
+ robots = 'index, nofollow'
+ bodyclass = 'mappage'
+%]
+
+[% map_html %]
+
+</div>
+
+
+[% IF banner.id %]
+ <div class="banner">
+ <p id="[% banner.id %]">[% banner.text %]</p>
+ </div>
+[% END %]
+
+[% INCLUDE 'report/_main.html' %]
+
+<div class="shadow-wrap">
+ <ul id="key-tools">
+ <li><a rel="nofollow" id="key-tool-report-abuse" class="abuse" href="[% c.uri_for( '/contact', { id => problem.id } ) %]">[% loc('Report abuse' ) %]</a></li>
+ <li><a rel="nofollow" id="key-tool-report-updates" class="feed" href="[% c.uri_for( '/alert/subscribe', { id => problem.id } ) %]">[% loc('Get updates' ) %]</a></li>
+ <li><a class="chevron" id="key-tool-problems-nearby" href="[% c.uri_for( '/around', { lat => short_latitude, lon => short_longitude } ) %]">[% loc( 'Problems nearby' ) %]</a></li>
+ </ul>
+
+<div id="report-updates-data" class="hidden-js">
+ <form action="[% c.uri_for( '/alert/subscribe' ) %]" method="post">
+ <p><a href="[% c.uri_for( '/rss', problem.id ) %]">
+ <img src="/i/feed.png" width="16" height="16" title="[% loc('RSS feed') %]" alt="[% loc('RSS feed of updates to this problem' ) %]" border="0" style="float: right">
+ </a></p>
+ <p>[% loc('Receive email when updates are left on this problem.' ) %]</p>
+ <fieldset>
+ <label class="hidden n" for="alert_rznvy">[% loc('Your email') %]</label>
+ <div class="form-txt-submit-box">
+ <input type="email" name="rznvy" id="alert_rznvy" value="[% email | html %]" size="30" placeholder="[% loc('Your email') %]">
+ <input class="green-btn" type="submit" value="[% loc('Subscribe') %]">
+ </div>
+ <input type="hidden" name="id" value="[% problem.id %]">
+ <input type="hidden" name="type" value="updates">
+ </fieldset>
+ </form>
+</div>
+
+</div>
+
+[% INCLUDE 'report/updates.html' %]
+
+<div id="update_form">
+ <h2>[% loc( 'Provide an update') %]</h2>
+
+ [% IF c.cobrand.moniker != 'emptyhomes' %]
+ <div class="general-sidebar-notes">
+ <p>[% loc( 'Please note that updates are not sent to the council. 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>' ) %]</p>
+ </div>
+ [% END %]
+
+ [% INCLUDE 'errors.html' %]
+
+ <form method="post" action="[% c.uri_for( '/report/update' ) %]" name="updateForm" class="validate"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %]>
+ <fieldset>
+ <input type="hidden" name="submit_update" value="1">
+ <input type="hidden" name="id" value="[% problem.id | html %]">
+
+ <label for="form_update">[% loc( 'Update' ) %]</label>
+ [% IF field_errors.update %]
+ <div class='form-error'>[% field_errors.update %]</div>
+ [% END %]
+ <textarea rows="7" cols="30" name="update" id="form_update" placeholder="[% loc('Please write your update here') %]" required>[% update.text | html %]</textarea>
+
+ [% IF c.user && c.user.belongs_to_council( problem.council ) %]
+ <label for="form_state">[% loc( 'State' ) %]</label>
+ <select name="state" id="form_state">
+ [% FOREACH state IN [ ['confirmed', loc('Open')], ['investigating',
+ loc('Investigating')], ['planned', loc('Planned')], ['in progress',
+ loc('In Progress')], ['closed', loc('Closed')], ['fixed', loc('Fixed')] ] %]
+ <option [% 'selected ' IF state.0 == problem.state %] value="[% state.0 %]">[% state.1 %]</option>
+ [% END %]
+ </select>
+ [% ELSE %]
+ [% IF problem.is_fixed AND c.user_exists AND c.user.id == problem.user_id %]
+
+ <input type="checkbox" name="reopen" id="form_reopen" value="1"[% ' checked' IF update.mark_open %]>
+ <label class="inline" for="form_reopen">[% loc('This problem has not been fixed') %]</label>
+
+ [% ELSIF !problem.is_fixed %]
+
+ <div class="checkbox-group">
+ <input type="checkbox" name="fixed" id="form_fixed" value="1"[% ' checked' IF update.mark_fixed %]>
+ <label class="inline" for="form_fixed">[% loc('This problem has been fixed') %]</label>
+ </div>
+
+ [% END %]
+ [% END %]
+
+ [% IF c.cobrand.allow_photo_upload %]
+ <div id="fileupload_normalUI">
+ [% IF upload_fileid %]
+ <img align="right" src="/photo/[% upload_fileid %].temp.jpeg" alt="">
+ <p>[% loc('You have already attached a photo to this update, attaching another one will replace it.') %]</p>
+ <input type="hidden" name="upload_fileid" value="[% upload_fileid %]">
+ [% END %]
+ <label for="form_photo">[% loc('Photo') %]</label>
+ [% IF field_errors.photo %]
+ <p class='form-error'>[% field_errors.photo %]</p>
+ [% END %]
+ <input type="file" name="photo" id="form_photo">
+ </div>
+ [% END %]
+
+ [% IF c.user_exists %]
+
+ [% INCLUDE name %]
+
+ <input class="final-submit green-btn" type="submit" id="update_post" value="[% loc('Post') %]">
+
+
+ [% ELSE %]
+
+ <label for="form_rznvy">[% loc('Email' ) %]</label>
+ [% IF field_errors.email %]
+ <p class='form-error'>[% field_errors.email %]</p>
+ [% END %]
+ <input type="email" name="rznvy" id="form_rznvy" value="[% update.user.email | html %]" placeholder="[% loc('Your email address' ) %]" required>
+
+ <div id="form_sign_in">
+ <h3>[% loc("Now to submit your update&hellip;") %]</h3>
+ <h2>[% loc("Do you have a FixMyStreet password?") %]</h2>
+
+ <div id="form_sign_in_no" class="form-box">
+ <h5>[% loc('<strong>No</strong> Let me confirm my update by email') %]</h5>
+
+ [% INCLUDE name %]
+
+ <div class="general-sidebar-notes">
+ <p class="dark">[% loc('We never show your email') %]</p>
+ <p>[% loc('Providing a password is optional, but doing so will allow you to more easily report problems, leave updates and manage your reports.') %]</p>
+ </div>
+
+ <label for="password_register">[% loc('Password (optional)') %]</label>
+
+ <div class="form-txt-submit-box">
+ <input type="password" name="password_register" id="password_register" value="" placeholder="[% loc('Enter a password') %]">
+ <input class="green-btn" type="submit" name="submit_register" id="submit_register" value="[% loc('Post') %]">
+ </div>
+ </div>
+ <div id="form_sign_in_yes" class="form-box">
+ <h5>[% loc('<strong>Yes</strong> I have a password') %]</h5>
+
+ <label class="hidden-js n" for="password_sign_in">[% loc('Yes I have a password') %]</label>
+ [% IF field_errors.password %]
+ <p class='form-error'>[% field_errors.password %]</p>
+ [% END %]
+ <div class="form-txt-submit-box">
+ <input type="password" name="password_sign_in" id="password_sign_in" value="" placeholder="[% loc('Your password') %]">
+ <input class="green-btn" type="submit" name="submit_sign_in" id="submit_sign_in" value="[% loc('Post') %]">
+ </div>
+
+ <div class="checkbox-group">
+ <input type="checkbox" id="remember_me" name="remember_me" value='1'[% ' checked' IF remember_me %]>
+ <label class="inline n" for="remember_me">[% loc('Keep me signed in on this computer') %]</label>
+ </div>
+ </div>
+ </div>
+
+ [% END %]
+ </fieldset>
+ </form>
+</div>
+
+
+
+[% INCLUDE 'footer.html' %]
+
+[% BLOCK name %]
+ [% IF problem.council == '2482' %]
+ [% extra_name_info = 1 %]
+ [% INCLUDE 'report/new/extra_name.html' %]
+ [% END %]
+
+ [% IF c.user_exists %]
+ [% names = c.user.split_name %]
+ [% END %]
+ <label for="form_first_name">[% loc('First Name') %]</label>
+ [% IF field_errors.first_name %]
+ <p class='form-error'>[% field_errors.first_name %]</p>
+ [% END %]
+ <input type="text" value="[% names.first || first_name | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]">
+
+ <label for="form_last_name">[% loc('Last Name') %]</label>
+ [% IF field_errors.last_name %]
+ <p class='form-error'>[% field_errors.last_name %]</p>
+ [% END %]
+ <input type="text" value="[% names.last || last_name | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]">
+
+ <div class="checkbox-group">
+ <input type="checkbox" name="may_show_name" id="form_may_show_name" value="1"[% ' checked' UNLESS update.anonymous %]>
+ <label class="inline" for="form_may_show_name">[% loc('Show my name publicly') %]</label>
+ </div>
+ <div class="checkbox-group">
+ <input type="checkbox" name="add_alert" id="form_add_alert" value="1"[% ' checked' IF add_alert %]>
+ <label class="inline" for="form_add_alert">[% loc( 'Alert me to future updates' ) %]</label>
+ </div>
+[% END %]
diff --git a/templates/web/bromley/report/new/fill_in_details_form.html b/templates/web/bromley/report/new/fill_in_details_form.html
new file mode 100644
index 000000000..5729f1637
--- /dev/null
+++ b/templates/web/bromley/report/new/fill_in_details_form.html
@@ -0,0 +1,230 @@
+<div id="report-a-problem-main">
+ <h1>[% loc('Reporting a problem') %]</h1>
+
+ [% IF js %]
+ <p id="councils_text">
+ [%
+ tprintf(
+ loc('All the information you provide here will be sent to <strong>%s</strong>.'),
+ loc('the local council')
+ );
+ %]
+ [% loc('The subject and details of the problem will be public, plus your name if you give us permission.') %]
+ </p>
+ [% ELSE %]
+ [% PROCESS 'report/new/councils_text.html' %]
+ [% END %]
+
+ <div id="report-a-problem-sidebar">
+ <!--
+ The text for this section needs checking, but I can't work out which bit comes from where
+ -->
+ <div class="sidebar-tips">
+ [% IF report.used_map %]
+ [% IF partial_token %]
+ <p id="unknown">[% loc('Please note your report has <strong>not yet been sent</strong>. Choose a category and add further information below, then submit.') %]</p>
+ [% END %]
+ <p>[% loc('You have located the problem at the point marked with a green pin on the map. If this is not the correct location, simply click on the map again. ') %]</p>
+ [% END %]
+
+ <p>
+ [% IF report.used_map %]
+ [% INCLUDE 'report/new/fill_in_details_text.html' %]
+ [% ELSE %]
+ [% loc('Please fill in the form below with details of the problem, and describe the location as precisely as possible in the details box.') %]
+ [% END %]
+ </p>
+ </div>
+
+ <div class="sidebar-notes">
+ [% INCLUDE 'report/new/notes.html' %]
+ </div>
+
+ </div>
+
+ [% INCLUDE 'errors.html' %]
+ <fieldset>
+ <div id="problem_form">
+
+ [% INCLUDE 'report/new/form_heading.html' %]
+
+
+ [% IF field_errors.council %]
+ <p class='form-error'>[% field_errors.council %]</p>
+ [% END %]
+
+
+
+ <label for="form_title">[% loc('Subject') %]</label>
+ [% IF field_errors.title %]
+ <p class='form-error'>[% field_errors.title %]</p>
+ [% END %]
+ <input type="text" value="[% report.title | html %]" name="title" id="form_title" placeholder="[% loc('Provide a title') %]" required>
+
+ <label for="form_detail">[% loc('Details') %]</label>
+ [% IF field_errors.detail %]
+ <p class='form-error'>[% field_errors.detail %]</p>
+ [% END %]
+ <textarea rows="7" cols="26" name="detail" id="form_detail" placeholder="[% loc('Please fill in details of the problem.') %]" required>[% report.detail | html %]</textarea>
+
+ [% IF js %]
+ <div id="form_category_row">
+ <label for="form_category">[% loc('Category') %]</label>
+ <select name="category" id="form_category" required><option>[% loc('Loading...') %]</option></select>
+ </div>
+ [% ELSE %]
+ [% IF category_options.size %]
+ [% IF field_errors.category %]
+ <p class='form-error'>[% field_errors.category %]</p>
+ [% END %]
+
+ [% PROCESS "report/new/category.html" %]
+ [% END %]
+ [% END %]
+
+ [%- IF category_extras %]
+ [% PROCESS "report/new/category_extras.html" %]
+ [%- END %]
+
+ [% IF c.cobrand.allow_photo_upload %]
+ [% IF field_errors.photo %]
+ <p class='form-error'>[% field_errors.photo %]</p>
+ [% END %]
+
+
+ [% IF upload_fileid || report.photo %]
+ [% IF upload_fileid %]
+ <img align="right" src="/photo/[% upload_fileid %].temp.jpeg" alt="">
+ <input type="hidden" name="upload_fileid" value="[% upload_fileid %]">
+ [% END %]
+
+ <p>[% loc('You have already attached a photo to this report, attaching another one will replace it.') %]</p>
+
+ [% IF report.photo %]
+ <img align="right" src="/photo/[% report.id %].jpeg">
+ [% END %]
+ [% END %]
+
+ <label for="form_photo">[% loc('Photo') %]</label>
+ <input type="file" name="photo" id="form_photo">
+ [% END %]
+
+ [% IF c.user_exists %]
+ <div class="form-box">
+ [% INCLUDE 'report/new/extra_name.html' %]
+
+ [% names = c.user.split_name %]
+ <label for="form_first_name">[% loc('First Name') %]</label>
+ [% IF field_errors.first_name %]
+ <p class='form-error'>[% field_errors.first_name %]</p>
+ [% END %]
+ <input type="text" value="[% ( first_name || names.first ) | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]">
+
+ <label for="form_last_name">[% loc('Last Name') %]</label>
+ [% IF field_errors.last_name %]
+ <p class='form-error'>[% field_errors.last_name %]</p>
+ [% END %]
+ <input type="text" value="[% ( last_name || names.last ) | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]">
+
+
+ [%# if there is nothing in the name field then set check box as default on form %]
+ <div class="checkbox-group">
+ <input type="checkbox" name="may_show_name" id="form_may_show_name" value="1"[% ' checked' IF !report.anonymous %]>
+ <label class="inline" for="form_may_show_name">[% loc('Show my name publicly') %]</label>
+ </div>
+
+ <div class="general-sidebar-notes">
+ <p>[% loc('We never show your email address or phone number.') %]</p>
+ </div>
+
+ <label for="form_phone">[% loc('Phone number (optional)') %]</label>
+ <input class="" type="text" value="[% report.user.phone | html %]" name="phone" id="form_phone" placeholder="[% loc('Your phone number') %]">
+
+ <div class="form-txt-submit-box">
+ <input class="green-btn" type="submit" id="submit_register" name="submit_register" value="[% loc('Submit') %]">
+ </div>
+ </div>
+ [% ELSE %]
+
+ <label for="form_email">[% loc('Your email') %]</label>
+ [% IF field_errors.email %]
+ <p class='form-error'>[% field_errors.email %]</p>
+ [% END %]
+ <input type="email" value="[% report.user.email | html %]" name="email" id="form_email" placeholder="[% loc('Please enter your email address') %]" required>
+
+ <div id="form_sign_in">
+ <h3>[% loc("Now to submit your report&hellip;") %]</h3>
+ <h2>[% loc("Do you have a FixMyStreet password?") %]</h2>
+
+ <div id="form_sign_in_no" class="form-box">
+ <h5>[% loc('<strong>No</strong> Let me confirm my report by email') %]</h5>
+
+ [% INCLUDE 'report/new/extra_name.html' %]
+
+ <label for="form_first_name">[% loc('First Name') %]</label>
+ [% IF field_errors.first_name %]
+ <p class='form-error'>[% field_errors.first_name %]</p>
+ [% END %]
+ <input type="text" class="form-focus-trigger" value="[% first_name | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]">
+
+ <label for="form_last_name">[% loc('Last Name') %]</label>
+ [% IF field_errors.last_name %]
+ <p class='form-error'>[% field_errors.last_name %]</p>
+ [% END %]
+ <input type="text" class="form-focus-trigger" value="[% last_name | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]">
+
+ [%# if there is nothing in the name field then set check box as default on form %]
+ <div class="checkbox-group">
+ <input type="checkbox" name="may_show_name" id="form_may_show_name" value="1"[% ' checked' IF !report.anonymous %]>
+ <label class="inline" for="form_may_show_name">[% loc('Show my name publicly') %]</label>
+ </div>
+
+ <div class="general-sidebar-notes form-focus-hidden">
+ <p class="dark">[% loc('We never show your email address or phone number.') %]</p>
+ <p>[% loc('Providing a password is optional, but doing so will allow you to more easily report problems, leave updates and manage your reports.') %]</p>
+ </div>
+
+ <label class="form-focus-hidden" for="form_phone">[% loc('Phone number (optional)') %]</label>
+ <input class="form-focus-hidden" type="text" value="[% report.user.phone | html %]" name="phone" id="form_phone" placeholder="[% loc('Your phone number') %]">
+
+ <label class="form-focus-hidden" for="password_register">[% loc('Password (optional)') %]</label>
+
+ <div class="form-txt-submit-box form-focus-hidden">
+ <input type="password" name="password_register" id="password_register" value="" placeholder="[% loc('Enter a password') %]">
+ <input class="green-btn" type="submit" id="submit_register" name="submit_register" value="[% loc('Submit') %]">
+ </div>
+ </div>
+
+ <div id="form_sign_in_yes" class="form-box">
+
+ <h5>[% loc('<strong>Yes</strong> I have a password') %]</h5>
+
+ <label class="hidden-js n" for="password_sign_in">[% loc('Yes I have a password') %]</label>
+ <div class="form-txt-submit-box">
+ [% IF field_errors.password %]
+ <p class='form-error'>[% field_errors.password %]</p>
+ [% END %]
+ <input type="password" name="password_sign_in" id="password_sign_in" placeholder="[% loc('Your password') %]" value="">
+ <input class="green-btn" type="submit" id="submit_sign_in" name="submit_sign_in" value="[% loc('Submit') %]">
+ </div>
+
+ <div class="checkbox-group">
+ <input type="checkbox" id="remember_me" name="remember_me" value='1'[% ' checked' IF remember_me %]>
+ <label class="n inline" for="remember_me">[% loc('Keep me signed in on this computer') %]</label>
+ </div>
+ </div>
+
+ </div>
+
+ <p>[% loc("We will only use your personal information in accordance with our <a href=\"/faq#privacy\">privacy policy.</a>") %]</p>
+
+ [% END %]
+ </div>
+ </fieldset>
+
+ [% IF partial_token %]
+ <input type="hidden" name="partial" value="[% partial_token.token %]">
+ [% END %]
+
+ <input type="hidden" name="submit_problem" value="1">
+</div>
diff --git a/templates/web/default/admin/report_edit.html b/templates/web/default/admin/report_edit.html
index cbba1b3b0..9ef7e8248 100644
--- a/templates/web/default/admin/report_edit.html
+++ b/templates/web/default/admin/report_edit.html
@@ -37,6 +37,7 @@
<li>[% loc('Service:') %] [% problem.service %]</li>
<li>[% loc('Cobrand:') %] [% problem.cobrand %]</li>
<li>[% loc('Cobrand data:') %] [% problem.cobrand_data %]</li>
+<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>
diff --git a/templates/web/default/common_header_tags.html b/templates/web/default/common_header_tags.html
index e74ae7b70..4931e8230 100644
--- a/templates/web/default/common_header_tags.html
+++ b/templates/web/default/common_header_tags.html
@@ -7,7 +7,8 @@
<script src="[% version('/js/jquery.validate.min.js') %]" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" src="[% version('/js/geo.min.js') %]"></script>
-<script type="text/javascript" src="[% version(js_override || '/js/fixmystreet.js') %]"></script>
+<script type="text/javascript" src="[% version('/js/fixmystreet.js') %]"></script>
+<script type="text/javascript" src="[% version(js_override || '/js/fixmystreet-old-box.js') %]"></script>
[% map_js %]
diff --git a/templates/web/default/faq/faq-en-gb.html b/templates/web/default/faq/faq-en-gb.html
index ed9d53c24..cc9ba979a 100755
--- a/templates/web/default/faq/faq-en-gb.html
+++ b/templates/web/default/faq/faq-en-gb.html
@@ -93,7 +93,8 @@ href="https://secure.mysociety.org/donate/">please do</a>.</dd>
to find out where reports go at the moment. Also <a href="/contact">contact us</a>
to update the address or addresses we use.</dd>
<dt>I&rsquo;m from a council, can we have FixMyStreet on our website?</dt>
- <dd>Yes you can! We offer branded, hosted versions of FixMyStreet for local council websites. <a href="/for-councils">Full details</a>.</dd>
+ <dd>Yes you can! We offer branded, hosted versions of FixMyStreet for local council websites.
+ <a href="http://www.fixmystreet.com/for-councils">Full details</a>.</dd>
<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
diff --git a/templates/web/default/js/validation_strings.html b/templates/web/default/js/validation_strings.html
index 70a0ed41c..71637877a 100644
--- a/templates/web/default/js/validation_strings.html
+++ b/templates/web/default/js/validation_strings.html
@@ -14,5 +14,8 @@
email: {
required: '[% loc('Please enter your email') %]',
email: '[% loc('Please enter a valid email') %]'
- }
+ },
+ fms_extra_title: '[% loc('Please enter your title') %]',
+ first_name: '[% loc('Please enter your first name') %]',
+ last_name: '[% loc('Please enter your second name') %]'
};
diff --git a/templates/web/default/report/new/extra_name.html b/templates/web/default/report/new/extra_name.html
new file mode 100644
index 000000000..ea523410b
--- /dev/null
+++ b/templates/web/default/report/new/extra_name.html
@@ -0,0 +1,15 @@
+[% IF extra_name_info %]
+<label for="form_fms_extra_title">Title</label>
+[% IF field_errors.fms_extra_title %]
+ <p class='form-error'>[% field_errors.fms_extra_title %]</p>
+[% END %]
+<select class="form-focus-trigger" id="form_fms_extra_title"
+ name="fms_extra_title">
+ <option></option>
+ <option value="Mr"[% ' selected' IF fms_extra_title == 'Mr' %]>Mr</option>
+ <option value="Miss"[% ' selected' IF fms_extra_title == 'Miss' %]>Miss</option>
+ <option value="Mrs"[% ' selected' IF fms_extra_title == 'Mrs' %]>Mrs</option>
+ <option value="Ms"[% ' selected' IF fms_extra_title == 'Ms' %]>Ms</option>
+ <option value="Dr"[% ' selected' IF fms_extra_title == 'Dr' %]>Dr</option>
+</select>
+[% END %]
diff --git a/templates/web/default/reports/council.html b/templates/web/default/reports/council.html
index 0d3d43d82..4eef35dec 100755
--- a/templates/web/default/reports/council.html
+++ b/templates/web/default/reports/council.html
@@ -1,3 +1,9 @@
+[% IF c.cobrand.moniker == 'fixmystreet' OR c.cobrand.moniker == 'bromley';
+ style = 'new';
+ ELSE;
+ style = 'old';
+ END;
+%]
[% IF ward %]
[% name = "$ward.name, $council.name"
thing = loc('ward')
@@ -19,7 +25,7 @@
[% map_html %]
-[% IF c.cobrand.moniker != 'fixmystreet' AND children.size %]
+[% IF style != 'new' AND children.size %]
<h2 style="clear:right">[% loc('Wards of this council') %]</h2>
<p>[% loc('Follow a ward link to view only reports within that ward.') %]</p>
<ul>
@@ -66,7 +72,7 @@ Its area is now covered by <a href="/reports/Bedford">Bedford Borough Council</a
<a href="/reports/Central+Bedfordshire">Central Bedfordshire Council</a>.
[% END %]
</p>
-[% ELSIF c.cobrand.moniker == 'fixmystreet' %]
+[% ELSIF style == 'new' %]
<div class="shadow-wrap">
<ul id="key-tools"[% IF NOT children.size %] class="singleton"[% END %]>
<li><a rel="nofollow" id="key-tool-updates-area" class="feed" href="[% rss_url %]">[% tprintf(loc('Get updates of problems in this %s'), thing) %]</a></li>
@@ -81,7 +87,7 @@ Its area is now covered by <a href="/reports/Bedford">Bedford Borough Council</a
[% TRY %][% INCLUDE 'reports/cobrand_stats.html' %][% CATCH file %][% END %]
-[% IF c.cobrand.moniker == 'fixmystreet' AND children.size %]
+[% IF style == 'new' AND children.size %]
<section id="council_wards" class="hidden-js">
<h2>[% loc('Wards of this council') %]</h2>
<p>[% loc('Follow a ward link to view only reports within that ward.') %]</p>
@@ -117,7 +123,7 @@ Its area is now covered by <a href="/reports/Bedford">Bedford Borough Council</a
[% IF problems %]
<ul class="issue-list-a">
-[% IF c.cobrand.moniker == 'fixmystreet' %]
+[% IF style == 'new' %]
[% FOREACH problem IN problems %]
<li>
diff --git a/templates/web/fixmystreet/alert/index.html b/templates/web/fixmystreet/alert/index.html
index 8d4459c01..010dfe55c 100644
--- a/templates/web/fixmystreet/alert/index.html
+++ b/templates/web/fixmystreet/alert/index.html
@@ -2,6 +2,18 @@
<h1>[% loc('Local RSS feeds and email alerts') %]</h1>
+[% IF photos.size %]
+<div class="sticky-sidebar">
+ <aside>
+ <h2>[% loc('Some photos of recent reports') %]</h2>
+ [% FOREACH p IN photos %]
+ <a href="/report/[% p.id %]"><img border="0" height="100"
+ src="/photo/[% p.id %].tn.jpeg" alt="[% p.title | html %]" title="[% p.title | html %]"></a>
+ [% END %]
+ </aside>
+</div>
+[% END %]
+
<p>
[% loc('FixMyStreet has a variety of RSS feeds and email alerts for local problems, including
alerts for all problems within a particular ward or council, or all problems
@@ -27,16 +39,4 @@ within a certain distance of a particular location.') %]
</fieldset>
</form>
-[% IF photos.size %]
-<div class="sticky-sidebar">
- <aside>
- <h2>[% loc('Some photos of recent reports') %]</h2>
- [% FOREACH p IN photos %]
- <a href="/report/[% p.id %]"><img border="0" height="100"
- src="/photo/[% p.id %].tn.jpeg" alt="[% p.title | html %]" title="[% p.title | html %]"></a>
- [% END %]
- </aside>
-</div>
-[% END %]
-
[% INCLUDE 'footer.html' %]
diff --git a/templates/web/fixmystreet/alert/list.html b/templates/web/fixmystreet/alert/list.html
index 8305fff6f..84899d457 100644
--- a/templates/web/fixmystreet/alert/list.html
+++ b/templates/web/fixmystreet/alert/list.html
@@ -20,7 +20,6 @@
<form id="alerts" name="alerts" method="post" action="/alert/subscribe">
-[%# XXX These photos should perhaps be in a vertical column on the right hand side, as currently. %]
[% IF photos.size %]
<div class="sticky-sidebar">
<aside>
diff --git a/templates/web/fixmystreet/around/around_index.html b/templates/web/fixmystreet/around/around_index.html
index 331f34325..d91ba928a 100644
--- a/templates/web/fixmystreet/around/around_index.html
+++ b/templates/web/fixmystreet/around/around_index.html
@@ -1,34 +1,37 @@
-[% INCLUDE 'header.html', title => loc('Reporting a problem'), bodyclass => 'mappage' %]
-
-[%
- # NOTE ON PARTIAL REPORTS:
- #
- # partial reports get a bit of extra text added, the form goes to
- # '/report/new' and the partial hidden field is added to the form.
-%]
-
+[% pre_container_extra = BLOCK %]
+<div id="front-main"><div id="front-main-container">
[%
question
= c.cobrand.enter_postcode_text()
|| loc("Enter a nearby GB postcode, or street name and area");
%]
-
<form action="[% c.uri_for('/around') %]" method="get" name="postcodeForm" id="postcodeForm">
- <fieldset>
- <label for="pc">[% question %]:</label>
+ <label for="pc">[% question %]:</label>
+ <div>
<input type="text" name="pc" value="[% pc | html %]" id="pc" size="10" maxlength="200">
- <input class="green-btn final-submit" type="submit" value="[% loc('Go') %]" id="submit">
+ <input type="submit" value="[% loc('Go') %]" id="submit">
+ </div>
- [% IF partial_token %]
- <input type="hidden" name="partial" value="[% partial_token.token %]">
- [% END %]
- </fieldset>
+ [% IF partial_token %]
+ <input type="hidden" name="partial" value="[% partial_token.token %]">
+ [% END %]
</form>
+</div></div>
+[% END %]
+
+[% INCLUDE 'header.html', title = loc('Reporting a problem'), bodyclass = 'frontpage fullwidthpage' %]
+
+[%
+ # NOTE ON PARTIAL REPORTS:
+ #
+ # partial reports get a bit of extra text added, the form goes to
+ # '/report/new' and the partial hidden field is added to the form.
+%]
[% IF location_offshore %]
- <p class="error">[% loc('That spot does not appear to be covered by a council. If you have tried to report an issue past the shoreline, for example, please specify the closest point on land.') %]</p>
+ <p class="form-error">[% loc('That spot does not appear to be covered by a council. If you have tried to report an issue past the shoreline, for example, please specify the closest point on land.') %]</p>
[% ELSIF location_error %]
- <p class="error">[% location_error %]</p>
+ <p class="form-error">[% location_error %]</p>
[% END %]
[% IF possible_location_matches %]
@@ -43,10 +46,8 @@
[% IF partial_token %]
<p style="margin-top: 0; color: #cc0000;">
<img align="right" src="/photo/[% partial_report.id %].jpeg" hspace="5">
- [% loc("Thanks for uploading your photo. We now need to locate your problem, so please enter a nearby street name or postcode in the box below&nbsp;:") %]
+ [% loc("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;:") %]
</p>
[% END %]
-
-
[% INCLUDE 'footer.html' %]
diff --git a/templates/web/fixmystreet/auth/sign_out.html b/templates/web/fixmystreet/auth/sign_out.html
index 3d8df60e4..23d39aa2d 100644
--- a/templates/web/fixmystreet/auth/sign_out.html
+++ b/templates/web/fixmystreet/auth/sign_out.html
@@ -1,8 +1,8 @@
-[% INCLUDE 'header.html', title => loc('Sign out') %]
+[% INCLUDE 'header.html', title = loc('Sign out'), bodyclass = 'fullwidthpage' %]
<h1>[% loc('You have been signed out') %]</h1>
-<p>Please feel free to <a href="[% c.uri_for('/auth') %]">sign in again</a>.</p>
-
+<p>Please feel free to <a href="[% c.uri_for('/auth') %]">sign in again</a>, or
+go back to the <a href="/">FixMyStreet front page</a>.</p>
[% INCLUDE 'footer.html' %]
diff --git a/templates/web/fixmystreet/header.html b/templates/web/fixmystreet/header.html
index 6be57891a..3ae3da6cb 100644
--- a/templates/web/fixmystreet/header.html
+++ b/templates/web/fixmystreet/header.html
@@ -18,7 +18,7 @@
<link rel="stylesheet" href="[% version('/cobrands/fixmystreet/layout.css') %]">
<![endif]-->
- <script src="[% version('/js/modernizr.custom.76759.js') %]" charset="utf-8"></script>
+ <script src="[% version('/js/modernizr.custom.js') %]" charset="utf-8"></script>
[% INCLUDE 'common_header_tags.html', js_override = '/cobrands/fixmystreet/fixmystreet.js' %]
<script src="[% version('/js/fancybox/jquery.fancybox-1.3.4.pack.js') %]" charset="utf-8"></script>
@@ -51,6 +51,8 @@
[% END %]
</div>
+ [% pre_container_extra %]
+
<div class="container">
<div class="content[% " $mainclass" | html IF mainclass %]" role="main">
diff --git a/templates/web/fixmystreet/index.html b/templates/web/fixmystreet/index.html
index 04b23ca7f..998a88469 100644
--- a/templates/web/fixmystreet/index.html
+++ b/templates/web/fixmystreet/index.html
@@ -16,13 +16,7 @@ Modernizr.load({
</script>
[% END %]
-[% INCLUDE 'header.html', title => '' , bodyclass => 'frontpage fullwidthpage' %]
-
-[% IF error %]
- <p class="error">[% error %]</p>
-[% END %]
-
-
+[% pre_container_extra = BLOCK %]
<div id="front-main">
<div id="front-main-container">
<h1>[% loc('Report, view, or discuss local problems') %]</h1>
@@ -44,6 +38,13 @@ Modernizr.load({
</form>
</div>
</div>
+[% END %]
+
+[% INCLUDE 'header.html', title = '', bodyclass = 'frontpage fullwidthpage' %]
+
+[% IF error %]
+ <p class="error">[% error %]</p>
+[% END %]
<div class="tablewrapper">
<div id="front-howto">
diff --git a/templates/web/fixmystreet/report/display.html b/templates/web/fixmystreet/report/display.html
index 0f650b7c2..72c637a5b 100644
--- a/templates/web/fixmystreet/report/display.html
+++ b/templates/web/fixmystreet/report/display.html
@@ -178,6 +178,10 @@
[% INCLUDE 'footer.html' %]
[% BLOCK name %]
+ [% IF problem.council == '2482' %]
+ [% extra_name_info = 1 %]
+ [% INCLUDE 'report/new/extra_name.html' %]
+ [% END %]
<label for="form_name">[% loc('Name') %]</label>
[% IF field_errors.name %]
<p class='form-error'>[% field_errors.name %]</p>
diff --git a/templates/web/fixmystreet/report/new/councils_text_all.html b/templates/web/fixmystreet/report/new/councils_text_all.html
index fb10ec4fd..2f06686d8 100644
--- a/templates/web/fixmystreet/report/new/councils_text_all.html
+++ b/templates/web/fixmystreet/report/new/councils_text_all.html
@@ -1,5 +1,5 @@
<p>
-[% IF all_councils.${area_ids_to_list.0}.type == 'LBO' %]
+[% IF all_councils.${area_ids_to_list.0}.type == 'LBO' AND area_ids_to_list.0 != 2482 %]
[%
tprintf(
loc('All the information you provide here will be sent to <strong>%s</strong> or a relevant local body such as <strong>TfL</strong>, via the London Report-It system.'),
@@ -16,4 +16,4 @@
[% END %]
[% loc('The subject and details of the problem will be public, plus your name if you give us permission.') %]
-</p> \ No newline at end of file
+</p>
diff --git a/templates/web/fixmystreet/report/new/fill_in_details_form.html b/templates/web/fixmystreet/report/new/fill_in_details_form.html
index 283f748ba..b8a813348 100644
--- a/templates/web/fixmystreet/report/new/fill_in_details_form.html
+++ b/templates/web/fixmystreet/report/new/fill_in_details_form.html
@@ -69,7 +69,7 @@
[% IF js %]
<div id="form_category_row">
- <label class="inline" for="form_category">[% loc('Category') %]</label>
+ <label for="form_category">[% loc('Category') %]</label>
<select name="category" id="form_category" required><option>[% loc('Loading...') %]</option></select>
</div>
[% ELSE %]
@@ -111,7 +111,7 @@
[% IF c.user_exists %]
<div class="form-box">
- <label for="form_may_show_nameme">[% loc('Name') %]</label>
+ <label for="form_name">[% loc('Name') %]</label>
[% IF field_errors.name %]
<p class='form-error'>[% field_errors.name %]</p>
[% END %]
@@ -168,10 +168,13 @@
<div id="form_sign_in_no" class="form-box">
<h5>[% loc('<strong>No</strong> Let me confirm my report by email') %]</h5>
- <label for="form_may_show_nameme">[% loc('Name') %]</label>
+ [% INCLUDE 'report/new/extra_name.html' %]
+
+ <label for="form_name">[% loc('Name') %]</label>
[% IF field_errors.name %]
<p class='form-error'>[% field_errors.name %]</p>
[% END %]
+
<input type="text" class="form-focus-trigger validName" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]">
[%# if there is nothing in the name field then set check box as default on form %]
diff --git a/templates/web/fixmystreet/report/new/notes.html b/templates/web/fixmystreet/report/new/notes.html
index 5a885abd0..eef172858 100644
--- a/templates/web/fixmystreet/report/new/notes.html
+++ b/templates/web/fixmystreet/report/new/notes.html
@@ -1,9 +1,11 @@
<p>[% loc("Please note:") %]</p>
<ul class="plain-list">
+[% IF c.cobrand.moniker != 'bromley' %]
<li>[% loc("We will only use your personal information in accordance with our <a href=\"/faq#privacy\">privacy policy.</a>") %]</li>
+[% END %]
<li>[% loc("Please be polite, concise and to the point.") %]</li>
<li>[% loc("Please do not be abusive &mdash; 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>[% loc("Remember that FixMyStreet is primarily for reporting physical problems that can be fixed. If your problem is not appropriate for submission via this site remember that you can contact your council directly using their own website.") %]</li>
-</ul> \ No newline at end of file
+</ul>
diff --git a/web/cobrands/bromley/base.scss b/web/cobrands/bromley/base.scss
index 4594f832f..710078118 100644
--- a/web/cobrands/bromley/base.scss
+++ b/web/cobrands/bromley/base.scss
@@ -5,3 +5,25 @@
@import "../fixmystreet/_base";
+// Want a white header, and logo is slightly bigger
+#site-header {
+ @include background(linear-gradient(#ddd, #fff 10%, #fff));
+ height: 4em;
+}
+
+// Colour tab to match colour scheme
+#nav-link {
+ width: 50px;
+ height: 48px;
+ background: url('/cobrands/bromley/tab-blue.png') 0 0 no-repeat;
+}
+
+// Change logo to logo of council
+#site-logo {
+ display: block;
+ width: 80px;
+ height: 44px;
+ top: 0.9em;
+ background: url('/cobrands/bromley/bromley-logo.s.jpg') 0 0 no-repeat;
+}
+
diff --git a/web/cobrands/bromley/bromley-logo.jpg b/web/cobrands/bromley/bromley-logo.jpg
new file mode 100644
index 000000000..28da8b7ea
--- /dev/null
+++ b/web/cobrands/bromley/bromley-logo.jpg
Binary files differ
diff --git a/web/cobrands/bromley/bromley-logo.s.jpg b/web/cobrands/bromley/bromley-logo.s.jpg
new file mode 100644
index 000000000..16f632848
--- /dev/null
+++ b/web/cobrands/bromley/bromley-logo.s.jpg
Binary files differ
diff --git a/web/cobrands/bromley/bromley.scss b/web/cobrands/bromley/bromley.scss
new file mode 100644
index 000000000..0f4879bef
--- /dev/null
+++ b/web/cobrands/bromley/bromley.scss
@@ -0,0 +1,108 @@
+/* Parts of Bromley'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 "compass";
+
+h1, h2, h3, h4, h5, h6, legend { font-family: 'Gill Sans', 'Trebuchet MS', Calibri, sans-serif; }
+body { color: #333; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; line-height: 1.4; }
+
+// #header renamed to #bromley-header
+#bromley-header { padding: 0 18px 0 25px; }
+
+.header-nav {float:right; background:url('http://www.bromley.gov.uk/site/styles/css_img/header-nav.gif') no-repeat; overflow:hidden; width:651px; height:34px; line-height:34px; padding:0 20px;}
+.header-nav li {float:left; width:130px; text-align:center; background:url('http://www.bromley.gov.uk/site/styles/css_img/header-nav-divider.gif') top right no-repeat;}
+.header-nav li:last-child {background:none;}
+.header-nav a:link, .header-nav a:visited {color:#fff; text-decoration:none;}
+.header-nav a:hover, .header-nav a:active {text-decoration:underline;}
+
+/* -------- For Google translate select box only */
+.header-nav div#google_translate_element .goog-te-gadget { font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; }
+.header-nav div#google_translate_element .goog-te-gadget .goog-te-combo { margin:5px 0 0 5px; padding:0 0 0 2px; background: #9b9b9b; color: #fff; border: 1px solid #606060; font-size: 12px; width: 138px;}
+.header-nav div#google_translate_element .goog-te-gadget .goog-te-combo option { background:#fff; color: #666; padding: 1px 0; margin: 0; }
+/* --- */
+
+.logo {padding:10px 0;}
+
+.sign-in {float:right; margin-top:-87px; width: 650px; text-align: right;}
+.sign-in a:link, .sign-in a:visited {color:#333; font-weight:bold; text-decoration:none;}
+.sign-in a:hover, .sign-in a:active {text-decoration:underline;}
+
+.main-menu {background:url('http://www.bromley.gov.uk/site/styles/css_img/main-menu.gif') no-repeat; width:689px; height:45px; margin-top:-60px; float:right; clear:right;}
+.main-menu li {float:left; width:126px; padding-right:2px; text-align:center; font:150%/45px 'Gill Sans', 'Trebuchet MS', Calibri, sans-serif;}
+.main-menu li a:link, .main-menu li a:visited {color:#fff; display:block; text-decoration:none;}
+.main-menu li a:hover, .main-menu li a:active {background:url('http://www.bromley.gov.uk/site/styles/css_img/main-menu-hover.gif') repeat-x;}
+.main-menu li.home a:hover, .main-menu li.home a:active {background:url('http://www.bromley.gov.uk/site/styles/css_img/main-menu-hover-home.gif') repeat-x;}
+
+#search { float: right; padding: 10px 17px; width: 270px; }
+#search label {display:none;}
+#search input { background: #ececec; border: 1px solid #768b9a; border-color: #768b9a #d1dee8 #d1dee8 #768b9a; line-height: 9px; padding: 6px 5px 4px; width: 184px; }
+#search input.button { background: #fff; border: 1px solid #8596a8; color: #333; font-family: 'Gill Sans', 'Trebuchet MS', Calibri, sans-serif; font-size:133%; height: 27px; line-height: 27px; padding: 0; vertical-align: top; width: 70px; }
+
+// #footer renamed to #bromley-footer, image removed from background, width removed for no scrollbar, fixed font size.
+#bromley-footer { background: #666; clear: both; padding:15px 15px 50px; margin-left:-15px; color:#fff; font-size:11px;}
+#bromley-footer a:link,
+#bromley-footer a:visited { color: #fff; text-decoration: none; }
+#bromley-footer a:hover,
+#bromley-footer a:active { text-decoration: underline;}
+#bromley-footer img { float: right; margin-top: -18px; }
+#bromley-footer .footer-nav { float: right; height:35px; margin-top: -15px; }
+#bromley-footer .footer-nav li { border-right:1px solid #fff; float: left; line-height: 1; padding: 0 20px; }
+#bromley-footer .footer-nav li:last-child { border: none; }
+
+// Bromley IE specific CSS
+.ie6 {
+ #search input { padding: 8px 5px 2px; }
+ #search input.button { padding: 0; width: 68px; line-height: 24px; }
+ input.button { overflow: visible; width: 1%; }
+}
+.ie7 {
+ #search input { padding: 8px 5px 2px; }
+ #search input.button { padding: 0; width: 68px; line-height: 24px; }
+ input.button { overflow: visible; }
+}
+.ie8 {
+ #search input { padding: 8px 5px 2px; }
+ #search input.button { padding: 0; line-height: 24px; }
+}
+
+// mySociety additions
+#bromley-header { font-size: 12px; }
+.header-nav ul { margin: 0; }
+.header-nav li { list-style-type: none; }
+.main-menu ul { margin: 0; }
+.main-menu li { list-style-type: none; }
+#search input { display: inline; margin: 0; @include border-radius(0em); }
+#search input.button { font-weight: normal; text-transform: none; }
+#bromley-footer { margin: 2em 0 0; }
+#bromley-footer .footer-nav li { list-style-type: none; }
+#bromley-footer p { margin: 0; }
+
+#bromley-powered-by {
+ text-align: right;
+}
+
+#main-menu {
+ text-align: center;
+ margin: 2em 0;
+ padding: 0;
+ li {
+ margin: 0;
+ padding: 0;
+ display: inline;
+ a, span {
+ padding: 1em;
+ color: #000;
+ background: #eef;
+ @include background(linear-gradient(#eef, #eee));
+ }
+ span {
+ text-decoration: underline;
+ }
+ }
+ a:hover {
+ background: #ccf;
+ }
+}
+
diff --git a/web/cobrands/bromley/favicon.ico b/web/cobrands/bromley/favicon.ico
new file mode 100644
index 000000000..cf0577755
--- /dev/null
+++ b/web/cobrands/bromley/favicon.ico
Binary files differ
diff --git a/web/cobrands/bromley/fms-logo.png b/web/cobrands/bromley/fms-logo.png
new file mode 100644
index 000000000..23bea6b0f
--- /dev/null
+++ b/web/cobrands/bromley/fms-logo.png
Binary files differ
diff --git a/web/cobrands/bromley/layout.scss b/web/cobrands/bromley/layout.scss
index 3dc34c6c7..6c2ded2fc 100644
--- a/web/cobrands/bromley/layout.scss
+++ b/web/cobrands/bromley/layout.scss
@@ -1,11 +1,113 @@
@import "_colours";
@import "../fixmystreet/_layout";
+// So that map appears underneath the header
+.wrapper {
+ position: relative;
+}
+.ie6, .ie7 {
+ .wrapper {
+ padding-top: 1em;
+ }
+}
+
body {
background: #fff;
}
#front-main {
background: $primary;
+ // layout sets this because base has it slightly lighter
+ h2 {
+ color: $primary_text;
+ }
+}
+
+// Don't want gap that normal site has
+body.frontpage {
+ .table-cell {
+ .content {
+ margin-top: 0;
+ }
+ }
+}
+#user-meta {
+ p {
+ top: -1em;
+ }
+}
+body.frontpage {
+ #user-meta {
+ p {
+ top: -2em;
+ }
+ }
+}
+
+// Don't want FixMyStreet logo on desktop, and we have a skip to content in
+// Bromley header
+#site-header {
+ display: none;
+}
+
+// Currently hiding, but do want some internal navigation somewhere at the end
+.nav-wrapper {
+ display: none;
+}
+
+// White background, so no shadow needed.
+.content {
+ margin-top: 1em;
+ @include box-shadow(none);
+}
+.ie6, .ie7, .ie8 {
+ .content {
+ border: none;
+ }
+}
+// Except on map pages
+body.mappage .content {
+ @include box-shadow(0px 0px 6px 1px #000);
+}
+.ie6, .ie7, .ie8 {
+ body.mappage .content {
+ border: solid 1px #666;
+ }
+}
+
+// As map can scroll and isn't at the top, give it an edge
+#map_box {
+ border-top: solid 1px #999;
+ border-bottom: solid 1px #999;
+}
+
+// Perhaps fix map location (should be in central?)
+.ie6 #map_box, .ie7 #map_box {
+ right: -30em;
+ top: 0;
+}
+
+// Fix location of aside sidebar
+body.twothirdswidthpage {
+ .content {
+ aside {
+ @include box-shadow(none);
+ }
+ .sticky-sidebar {
+ aside {
+ position: absolute;
+ top: 0;
+ }
+ }
+ }
+}
+@media only screen and (min-width: 48em) and (max-width: 61em) {
+ body.twothirdswidthpage {
+ .content {
+ .sticky-sidebar {
+ top: auto;
+ }
+ }
+ }
}
diff --git a/web/cobrands/bromley/tab-blue.png b/web/cobrands/bromley/tab-blue.png
new file mode 100644
index 000000000..62e6285b7
--- /dev/null
+++ b/web/cobrands/bromley/tab-blue.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/_base.scss b/web/cobrands/fixmystreet/_base.scss
index 4202564f7..5fd87a454 100644
--- a/web/cobrands/fixmystreet/_base.scss
+++ b/web/cobrands/fixmystreet/_base.scss
@@ -31,9 +31,6 @@ h1 {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
-#front-main h1 {
- margin-top: 0.7em;
-}
h1#reports_heading span {
display: none;
}
@@ -149,10 +146,9 @@ img {
select, input, textarea {
font-size: 99%;
- max-width: 95%;
+ max-width: 100%;
}
-
// links
a,
a:visited {
@@ -244,10 +240,19 @@ input[type=password],
input[type=email],
input[type=file],
textarea {
+ @include box-sizing(border-box);
width: 100%;
// adjust so the sides line up
padding: 0.5em;
- margin: 0 0 0 -0.5em;
+}
+.ie7 {
+ input[type=text],
+ input[type=password],
+ input[type=email],
+ input[type=file],
+ textarea {
+ max-width: 95%;
+ }
}
textarea {
@@ -291,7 +296,6 @@ label{
margin: 0 -2em 0.25em -2em;
background:#eeeeee;
padding:1em 2em 1em 2em;
- max-width:26em;
>input[type=text] {
margin-bottom:1em;
}
@@ -316,6 +320,14 @@ label{
// it looks okay.
.ie6 .form-box {
margin: 0 0 0.25em 0;
+ padding: 1em;
+}
+// Prevent grey displaying oddly by giving it a width, and stop odd left margin issue
+.ie7 .form-box {
+ width: 100%;
+ > input[type=text] {
+ margin-left: 2em;
+ }
}
.form-txt-submit-box {
@@ -347,8 +359,14 @@ p.form-error {
background:#ff0000;
color:#fff;
padding:0 0.5em;
- margin:0 0 0 -0.5em;
@include border-radius(0.25em 0.25em 0 0);
+ a {
+ color: white;
+ text-decoration: underline;
+ }
+ a:hover {
+ text-decoration: none;
+ }
}
input.form-error,
@@ -361,7 +379,6 @@ ul.error {
background:#ff0000;
color:#fff;
padding:0 0.5em;
- margin:0 0 0 -0.5em;
@include border-radius(0.25em);
}
@@ -447,7 +464,8 @@ p.label-valid {
&#mysoc-menu{
li {
a {
- background:$primary;
+ color: $primary_text;
+ background: $primary;
&#mysoc-logo {
background-image:url('/cobrands/fixmystreet/images/sprite.png');
background-repeat:no-repeat;
@@ -472,7 +490,8 @@ p.label-valid {
#user-meta {
p {
position: relative;
- background:$primary;
+ color: $primary_text;
+ background: $primary;
padding:1em 6em 1em 1em;
a {
position: absolute;
@@ -893,7 +912,7 @@ a:hover.button-left {
width:20px;
height:20px;
opacity: 0.5;
- background:#fff url(images/sprite.png) -16px -1098px no-repeat;
+ background:#fff url(/cobrands/fixmystreet/images/sprite.png) -16px -1098px no-repeat;
//hide text - http://nicolasgallagher.com/another-css-image-replacement-technique/
font: 0/0 a;
color: transparent;
@@ -1273,7 +1292,8 @@ table.nicetable {
.promo {
@extend .full-width;
- background:$primary;
+ color: $primary_text;
+ background: $primary;
padding:1em;
margin-bottom:1em;
overflow:hidden;
@@ -1286,10 +1306,10 @@ table.nicetable {
width:16px;
height:16px;
text-indent:-999999px;
- background:url(images/sprite.png) -341px -263px no-repeat;
+ background:url(/cobrands/fixmystreet/images/sprite.png) -341px -263px no-repeat;
@include border-radius(4px);
&:hover {
- background:#222 url(images/sprite.png) -341px -223px no-repeat;
+ background:#222 url(/cobrands/fixmystreet/images/sprite.png) -341px -223px no-repeat;
}
}
}
@@ -1320,7 +1340,8 @@ table.nicetable {
}
a {
@include inline-block;
- background:$primary;
+ color: $primary_text;
+ background: $primary;
padding-left:0.5em;
padding-right:0.5em;
color:#1a1a1a;
@@ -1334,7 +1355,7 @@ table.nicetable {
// this is a bit of a hack to get some differentation between desk and mobile
.desk-only {
- display:none !important;
+ display:none;
}
// hide anything with this class if js is working
@@ -1353,6 +1374,7 @@ table.nicetable {
/* Front page */
#front-main {
text-align:center;
+ margin: 1em;
h2 {
font: {
style:italic;
@@ -1361,6 +1383,9 @@ table.nicetable {
}
color:#4d4d4d;
}
+ p {
+ margin: 0.5em 0 0;
+ }
#postcodeForm {
@extend .full-width;
padding:1em;
@@ -1447,7 +1472,6 @@ table.nicetable {
#front-recently {
.issue-list-a {
border-bottom:none;
- margin-bottom:0;
}
}
diff --git a/web/cobrands/fixmystreet/_layout.scss b/web/cobrands/fixmystreet/_layout.scss
index 687b3dbcc..57b26f42d 100644
--- a/web/cobrands/fixmystreet/_layout.scss
+++ b/web/cobrands/fixmystreet/_layout.scss
@@ -3,10 +3,10 @@
//hacks for desk/mob only stuff
.desk-only {
- display:block !important;
+ display: block;
}
.mob-only {
- display:none !important;
+ display: none;
}
body {
@@ -147,7 +147,8 @@ h1 {
@include background(linear-gradient(#000, #444 10%, #444 95%, #111));
}
a.report-a-problem-btn {
- background:$primary;
+ color: $primary_text;
+ background: $primary;
padding:0.25em;
margin:0.5em;
color:#333;
@@ -210,7 +211,7 @@ h1 {
.ie6, .ie7, .ie8 {
.content {
// If no box-shadow, just want a boring black border to stand it out from the map.
- border: 1px solid black;
+ border: 1px solid #666;
//take off margins so we line up properly
margin: 0;
}
@@ -702,18 +703,13 @@ input[type=text],
input[type=password],
input[type=email],
textarea{
- width: 25em;
+ max-width: 25em;
}
-.form-box {
- max-width:25em;
-}
-
/* form errors */
div.form-error,
p.form-error {
display:block;
- width:24.7em;
}
input.form-error,
@@ -743,7 +739,7 @@ textarea.form-error {
}
}
.ie6, .ie7 {
- #report-a-problem-sidebar {
+ #report-a-problem-sidebar, .general-sidebar-notes {
left: 29em; // 0.5em left margin gone on .content in IE6/7, so reduce this accordingly.
}
}
@@ -782,19 +778,15 @@ textarea.form-error {
body.frontpage {
.table-cell {
- // we do this so we can have full screen width elements
- >.container {
- width:100%;
- }
.content {
- margin:14em auto 0 auto;
+ margin: 1em auto 0;
}
}
.nav-wrapper-2{
height:6em;
}
#site-header{
- height:9em;
+ height:8em;
}
#site-logo{
top:3em;
@@ -807,7 +799,7 @@ body.frontpage {
p {
top:-4em;
right:0;
- color:#FFD000;
+ color:$primary;
background:none;
@include box-shadow(rgba(0, 0, 0, 0) 0 0 0);
a {
@@ -833,7 +825,7 @@ body.frontpage {
.ie6, .ie7 {
body.frontpage {
#site-header {
- height:3em;
+ height:4em;
}
#site-logo {
top:-1em;
@@ -846,24 +838,13 @@ body.frontpage {
.ie6 body.frontpage #site-logo {
background:url(/cobrands/fixmystreet/images/ie_front_logo.gif) 0 0 no-repeat;
}
-//weird margining thing for ie8
-.ie8 body.frontpage {
- #front-main {
- top:-12em;
- }
- .table-cell .content {
- margin-top:12em;
- }
-}
// big yellow bit full screen width
#front-main {
color: $primary_text;
background: $primary url(/cobrands/fixmystreet/images/tile-y.jpg);
- position:absolute;
- width:100%;
- left:0;
- top:-15em;
+ margin: 0;
+ padding: 1em;
#front-main-container {
max-width: 57em;
margin:0 auto;
@@ -876,6 +857,7 @@ body.frontpage {
#postcodeForm {
background:none;
overflow:hidden;
+ padding-bottom: 0;
margin-right:0.5em;
label {
margin:0.5em 0;
@@ -889,8 +871,8 @@ body.frontpage {
display:block;
float:left;
padding:0.25em 0.5em;
- height:1.5em;
- width:16em;
+ height:2em;
+ width:17em;
}
input#submit {
display:block;
@@ -901,27 +883,40 @@ body.frontpage {
}
}
}
+ a {
+ color: $primary_text;
+ text-decoration: underline;
+ &:hover {
+ text-decoration: none;
+ }
+ }
a#geolocate_link {
background:none;
color:#222;
- margin:-1em 0 0.5em 0;
+ text-decoration: none;
+ padding-bottom: 0;
&:hover {
text-decoration:underline;
background:none;
}
}
}
-.ie6, .ie7 {
- #front-main {
- top:2em;
+.ie7 #front-main {
+ #postcodeForm {
+ div {
+ input#pc {
+ height:1.5em;
+ width:16em;
+ }
+ }
}
}
-
#front-howto {
border-right:1em solid #fff;
#front_stats {
background:none;
+ color: #222;
border-top:0.25em solid $primary;
padding-top:1em;
div {
diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js
index 0db8334fb..47f5da820 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -3,33 +3,6 @@
* FixMyStreet JavaScript
*/
-function form_category_onchange() {
- var cat = $('#form_category');
- var args = {
- category: cat.val()
- };
-
- if ( typeof fixmystreet !== 'undefined' ) {
- args.latitude = fixmystreet.latitude;
- args.longitude = fixmystreet.longitude;
- } else {
- args.latitude = $('input[name="latitude"]').val();
- args.longitude = $('input[name="longitude"]').val();
- }
-
- $.getJSON('/report/new/category_extras', args, function(data) {
- if ( data.category_extra ) {
- if ( $('#category_meta').size() ) {
- $('#category_meta').html( data.category_extra);
- } else {
- $('#form_category_row').after( data.category_extra );
- }
- } else {
- $('#category_meta').empty();
- }
- });
-}
-
/*
* general height fixing function
*
@@ -80,12 +53,12 @@ function tabs(elem, indirect) {
$(function(){
var $html = $('html');
- $html.removeClass('no-js').addClass('js');
-
-
- // Preload the new report pin
- document.createElement('img').src = '/i/pin-green.png';
+ var cobrand;
+ if (window.location.href.indexOf('bromley') != -1) {
+ cobrand = 'bromley';
+ }
+ // Deal with switching between mobile and desktop versions on resize
var last_type;
$(window).resize(function(){
var type = $('#site-header').css('borderTopWidth');
@@ -106,7 +79,9 @@ $(function(){
}
if (typeof fixmystreet !== 'undefined' && fixmystreet.page == 'around') {
// Immediately go full screen map if on around page
- $('#site-header').hide();
+ if (cobrand != 'bromley') {
+ $('#site-header').hide();
+ }
$('#map_box').prependTo('.wrapper').css({
position: 'absolute',
top: 0, left: 0, right: 0, bottom: 0,
@@ -128,23 +103,52 @@ $(function(){
} else {
// Make map full screen on non-mobile sizes.
$html.removeClass('mobile');
- var map_pos = 'fixed', map_height = '100%';
- if ($html.hasClass('ie6')) {
- map_pos = 'absolute';
- map_height = $(window).height();
+ if (cobrand == 'bromley') {
+ var $window = $(window), $content = $('.content'), o = $content.offset();
+ if ($html.hasClass('ie6')) {
+ $('#map_box').prependTo('.wrapper').css({
+ zIndex: 0, position: 'absolute',
+ right: 0, top: '1em',
+ width: $window.width() - o.left - $content.outerWidth(),
+ height: $window.height() - o.top + 32,
+ margin: 0
+ });
+ } else {
+ var map_height = $window.height() - o.top;
+ $('#map_box').prependTo('.wrapper').css({
+ zIndex: 0, position: 'fixed',
+ right: 0, top: o.top, bottom: 0, left: 'auto',
+ width: $window.width() - o.left - $content.outerWidth(),
+ height: map_height,
+ margin: 0
+ });
+ }
+ } else if ($html.hasClass('ie6')) {
+ $('#map_box').prependTo('.wrapper').css({
+ zIndex: 0, position: 'absolute',
+ top: 0, left: 0, right: 0, bottom: 0,
+ width: '100%', height: $(window).height(),
+ margin: 0
+ });
+ } else {
+ $('#map_box').prependTo('.wrapper').css({
+ zIndex: 0, position: 'fixed',
+ top: 0, left: 0, right: 0, bottom: 0,
+ width: '100%', height: '100%',
+ margin: 0
+ });
}
- $('#map_box').prependTo('.wrapper').css({
- zIndex: 0, position: map_pos,
- top: 0, left: 0, right: 0, bottom: 0,
- width: '100%', height: map_height,
- margin: 0
- });
if (typeof fixmystreet !== 'undefined') {
+ if (cobrand == 'bromley') {
+ $('#bromley-footer').hide();
+ }
fixmystreet.state_map = 'full';
}
if (typeof fixmystreet !== 'undefined' && fixmystreet.page == 'around') {
// Remove full-screen-ness
- $('#site-header').show();
+ if (cobrand != 'bromley') {
+ $('#site-header').show();
+ }
$('#fms_pan_zoom').css({ top: '4.75em !important' });
$('.big-green-banner')
.removeClass('mobile-map-banner')
@@ -154,141 +158,7 @@ $(function(){
$('span.report-a-problem-btn').css({ cursor:'' }).off('.reportBtn');
}
last_type = type;
- });
-
- //add mobile class if small screen
- $(window).resize();
-
- $('#pc').focus();
-
- $('input[type=submit]').removeAttr('disabled');
- /*
- $('#mapForm').submit(function() {
- if (this.submit_problem) {
- $('input[type=submit]', this).prop("disabled", true);
- }
- return true;
- });
- */
-
- if (!$('#been_fixed_no').prop('checked') && !$('#been_fixed_unknown').prop('checked')) {
- $('#another_qn').hide();
- }
- $('#been_fixed_no').click(function() {
- $('#another_qn').show('fast');
- });
- $('#been_fixed_unknown').click(function() {
- $('#another_qn').show('fast');
- });
- $('#been_fixed_yes').click(function() {
- $('#another_qn').hide('fast');
- });
-
- // FIXME - needs to use translated string
- jQuery.validator.addMethod('validCategory', function(value, element) {
- return this.optional(element) || value != '-- Pick a category --'; }, validation_strings.category );
-
- jQuery.validator.addMethod('validName', function(value, element) {
- var validNamePat = /\ba\s*n+on+((y|o)mo?u?s)?(ly)?\b/i;
- return this.optional(element) || value.length > 5 && value.match( /\S/ ) && !value.match( validNamePat ); }, validation_strings.category );
-
- var form_submitted = 0;
- var submitted = false;
-
- $("form.validate").validate({
- rules: {
- title: { required: true },
- detail: { required: true },
- email: { required: true },
- update: { required: true },
- rznvy: { required: true }
- },
- messages: validation_strings,
- onkeyup: false,
- onfocusout: false,
- errorElement: 'div',
- errorClass: 'form-error',
- // we do this to stop things jumping around on blur
- success: function (err) { if ( form_submitted ) { err.addClass('label-valid').removeClass('label-valid-hidden').html( '&nbsp;' ); } else { err.addClass('label-valid-hidden'); } },
- errorPlacement: function( error, element ) {
- element.before( error );
- },
- submitHandler: function(form) {
- if (form.submit_problem) {
- $('input[type=submit]', form).prop("disabled", true);
- }
-
- form.submit();
- },
- // make sure we can see the error message when we focus on invalid elements
- showErrors: function( errorMap, errorList ) {
- if ( submitted && errorList.length ) {
- $(window).scrollTop( $(errorList[0].element).offset().top - 120 );
- }
- this.defaultShowErrors();
- submitted = false;
- },
- invalidHandler: function(form, validator) { submitted = true; }
- });
-
- $('input[type=submit]').click( function(e) { form_submitted = 1; } );
-
- /* set correct required status depending on what we submit
- * NB: need to add things to form_category as the JS updating
- * of this we do after a map click removes them */
- $('#submit_sign_in').click( function(e) {
- $('#form_category').addClass('required validCategory').removeClass('valid');
- $('#form_name').removeClass();
- } );
-
- $('#submit_register').click( function(e) {
- $('#form_category').addClass('required validCategory').removeClass('valid');
- $('#form_name').addClass('required validName');
- } );
-
- $('#problem_submit > input[type="submit"]').click( function(e) {
- $('#form_category').addClass('required validCategory').removeClass('valid');
- $('#form_name').addClass('required validName');
- } );
-
- $('#update_post').click( function(e) {
- $('#form_name').addClass('required').removeClass('valid');
- } );
-
- $('#form_category').change( form_category_onchange );
-
- // Geolocation
- if (geo_position_js.init()) {
- $('#postcodeForm').after('<a href="#" id="geolocate_link">&hellip; or locate me automatically</a>');
- $('#geolocate_link').click(function(e) {
- e.preventDefault();
- // Spinny thing!
- if($('.mobile').length){
- $(this).append(' <img src="/cobrands/fixmystreet/images/spinner-black.gif" alt="" align="bottom">');
- }else{
- $(this).append(' <img src="/cobrands/fixmystreet/images/spinner-yellow.gif" alt="" align="bottom">');
- }
- geo_position_js.getCurrentPosition(function(pos) {
- $('img', this).remove();
- var latitude = pos.coords.latitude;
- var longitude = pos.coords.longitude;
- location.href = '/around?latitude=' + latitude + ';longitude=' + longitude;
- }, function(err) {
- $('img', this).remove();
- if (err.code == 1) { // User said no
- } else if (err.code == 2) { // No position
- $(this).html("Could not look up location");
- } else if (err.code == 3) { // Too long
- $('this').html("No result returned");
- } else { // Unknown
- $('this').html("Unknown error");
- }
- }, {
- enableHighAccuracy: true,
- timeout: 10000
- });
- });
- }
+ }).resize();
/*
* Report a problem page
@@ -572,7 +442,11 @@ $.fn.drawer = function(id, ajax) {
*/
if (!$('html.mobile').length) {
if (!($('body').hasClass('frontpage'))){
- heightFix(window, '.content', -176);
+ var offset = -176;
+ if (cobrand == 'bromley') {
+ offset = -110;
+ }
+ heightFix(window, '.content', offset);
}
}
diff --git a/web/css/core.scss b/web/css/core.scss
index a38a188ce..72e483dfa 100644
--- a/web/css/core.scss
+++ b/web/css/core.scss
@@ -114,7 +114,9 @@ $map_width: 500px;
}
}
- #geolocate_para {
+ #geolocate_link {
+ display: block;
+ border: none;
font-size: 70%;
margin: 2px 0 0 0;
text-align: right;
@@ -609,7 +611,7 @@ $map_width: 500px;
}
}
- #geolocate_para {
+ #geolocate_link {
font-size: 100%;
}
diff --git a/web/js/fixmystreet-old-box.js b/web/js/fixmystreet-old-box.js
new file mode 100644
index 000000000..72eeafb4d
--- /dev/null
+++ b/web/js/fixmystreet-old-box.js
@@ -0,0 +1,39 @@
+/*
+ * fixmystreet-old-box.js
+ * Create the 'email me updates' pop up box on old-style report display pages.
+ */
+
+$(function(){
+
+ if (!$('#email_alert_box').length) {
+ return;
+ }
+
+ var timer;
+ function email_alert_close() {
+ $('#email_alert_box').hide('fast');
+ }
+
+ $('#email_alert').click(function(e) {
+ e.preventDefault();
+ if ($('#email_alert_box').is(':visible')) {
+ email_alert_close();
+ } else {
+ var pos = $(this).position();
+ $('#email_alert_box').css( { 'left': ( pos.left - 20 ) + 'px', 'top': ( pos.top + 20 ) + 'px' } );
+ $('#email_alert_box').show('fast');
+ $('#alert_rznvy').focus();
+ }
+ }).hover(function() {
+ window.clearTimeout(timer);
+ }, function() {
+ timer = window.setTimeout(email_alert_close, 2000);
+ });
+
+ $('#email_alert_box').hover(function() {
+ window.clearTimeout(timer);
+ }, function() {
+ timer = window.setTimeout(email_alert_close, 2000);
+ });
+
+});
diff --git a/web/js/fixmystreet.js b/web/js/fixmystreet.js
index 834aa4ed3..36d47b5b2 100644
--- a/web/js/fixmystreet.js
+++ b/web/js/fixmystreet.js
@@ -1,51 +1,31 @@
/*
* fixmystreet.js
- * FixMyStreet JavaScript
+ * FixMyStreet JavaScript used by all cobrands.
+ * With the JavaScript written more proper like.
*/
-function form_category_onchange() {
- var cat = $('#form_category');
- var args = {
- category: cat.val()
- };
-
- if ( typeof fixmystreet !== 'undefined' ) {
- args.latitude = fixmystreet.latitude;
- args.longitude = fixmystreet.longitude;
- } else {
- args.latitude = $('input[name="latitude"]').val();
- args.longitude = $('input[name="longitude"]').val();
- }
-
- $.getJSON('/report/new/category_extras', args, function(data) {
- if ( data.category_extra ) {
- if ( $('#category_meta').size() ) {
- $('#category_meta').html( data.category_extra);
- } else {
- $('#form_category_row').after( data.category_extra );
- }
- } else {
- $('#category_meta').empty();
- }
- });
-}
+(function($){
+/*
+ Deal with changes to category by asking for details from the server.
+ */
$(function(){
- $('html').removeClass('no-js').addClass('js');
+ var $html = $('html');
+
+ // Add a class to the whole page saying JavaScript is enabled (for CSS and so on)
+ $html.removeClass('no-js').addClass('js');
+ // Preload the new report pin
+ document.createElement('img').src = '/i/pin-green.png';
+
+ // Focus on postcode box on front page
$('#pc').focus();
+ // In case we've come here by clicking back to a form that disabled a submit button
$('input[type=submit]').removeAttr('disabled');
- /*
- $('#mapForm').submit(function() {
- if (this.submit_problem) {
- $('input[type=submit]', this).prop("disabled", true);
- }
- return true;
- });
- */
+ // Questionnaire hide/showings
if (!$('#been_fixed_no').prop('checked') && !$('#been_fixed_unknown').prop('checked')) {
$('#another_qn').hide();
}
@@ -59,10 +39,7 @@ $(function(){
$('#another_qn').hide('fast');
});
- var timer;
- function email_alert_close() {
- $('#email_alert_box').hide('fast');
- }
+ // Form validation
// FIXME - needs to use translated string
jQuery.validator.addMethod('validCategory', function(value, element) {
@@ -85,12 +62,18 @@ $(function(){
},
messages: validation_strings,
onkeyup: false,
+ onfocusout: false,
errorElement: 'div',
errorClass: 'form-error',
// we do this to stop things jumping around on blur
success: function (err) { if ( form_submitted ) { err.addClass('label-valid').removeClass('label-valid-hidden').html( '&nbsp;' ); } else { err.addClass('label-valid-hidden'); } },
errorPlacement: function( error, element ) {
- element.parent('div').before( error );
+ // Different for old/new style design
+ if ($('.form-field').length) {
+ element.parent('div.form-field').before( error );
+ } else {
+ element.before( error );
+ }
},
submitHandler: function(form) {
if (form.submit_problem) {
@@ -102,7 +85,7 @@ $(function(){
// make sure we can see the error message when we focus on invalid elements
showErrors: function( errorMap, errorList ) {
if ( submitted && errorList.length ) {
- $(window).scrollTop( $(errorList[0].element).offset().top - 40 );
+ $(window).scrollTop( $(errorList[0].element).offset().top - 120 );
}
this.defaultShowErrors();
submitted = false;
@@ -112,83 +95,105 @@ $(function(){
$('input[type=submit]').click( function(e) { form_submitted = 1; } );
- /* set correct required status depending on what we submit
- * NB: need to add things to form_category as the JS updating
+ /* set correct required status depending on what we submit
+ * NB: need to add things to form_category as the JS updating
* of this we do after a map click removes them */
$('#submit_sign_in').click( function(e) {
$('#form_category').addClass('required validCategory').removeClass('valid');
$('#form_name').removeClass();
+ $('#form_first_name').removeClass();
+ $('#form_last_name').removeClass();
+ $('#form_fms_extra_title').removeClass();
} );
- $('#submit_register').click( function(e) {
+ $('#submit_register').click( function(e) {
$('#form_category').addClass('required validCategory').removeClass('valid');
$('#form_name').addClass('required validName');
+ $('#form_first_name').addClass('required');
+ $('#form_last_name').addClass('required');
+ $('#form_fms_extra_title').addClass('required');
} );
- $('#problem_submit > input[type="submit"]').click( function(e) {
+ $('#problem_submit > input[type="submit"]').click( function(e) {
$('#form_category').addClass('required validCategory').removeClass('valid');
$('#form_name').addClass('required validName');
+ $('#form_first_name').addClass('required');
+ $('#form_last_name').addClass('required');
+ $('#form_fms_extra_title').addClass('required');
} );
- $('#update_post').click( function(e) {
+ $('#update_post').click( function(e) {
$('#form_name').addClass('required').removeClass('valid');
} );
- $('#email_alert').click(function(e) {
- if (!$('#email_alert_box').length) {
- return true;
- }
- e.preventDefault();
- if ($('#email_alert_box').is(':visible')) {
- email_alert_close();
- } else {
- var pos = $(this).position();
- $('#email_alert_box').css( { 'left': ( pos.left - 20 ) + 'px', 'top': ( pos.top + 20 ) + 'px' } );
- $('#email_alert_box').show('fast');
- $('#alert_rznvy').focus();
- }
- }).hover(function() {
- window.clearTimeout(timer);
- }, function() {
- timer = window.setTimeout(email_alert_close, 2000);
- });
-
- $('#email_alert_box').hover(function() {
- window.clearTimeout(timer);
- }, function() {
- timer = window.setTimeout(email_alert_close, 2000);
- });
-
- // Using delegate here because we *might* be running under a cobrand which isn't jQuery 1.7+
- // Delegation is necessary because #form_category may be replaced during the lifetime of the page
- $("#problem_form").delegate("select#form_category", "change", form_category_onchange );
-
// Geolocation
if (geo_position_js.init()) {
- $('#postcodeForm').append('<p id="geolocate_para">Or <a href="#" id="geolocate_link">locate me automatically</a>').css({ "padding-bottom": "0.5em" });
+ if ($('body.frontpage').length) {
+ $('#postcodeForm').after('<a href="#" id="geolocate_link">&hellip; or locate me automatically</a>');
+ } else{
+ $('#postcodeForm').append('<a href="#" id="geolocate_link">&hellip; or locate me automatically</a>');
+ }
$('#geolocate_link').click(function(e) {
+ var $link = $(this);
e.preventDefault();
// Spinny thing!
- $('#geolocate_para').append(' <img src="/i/flower.gif" alt="" align="bottom">');
+ if($('.mobile').length){
+ $link.append(' <img src="/cobrands/fixmystreet/images/spinner-black.gif" alt="" align="bottom">');
+ }else{
+ $link.append(' <img src="/cobrands/fixmystreet/images/spinner-yellow.gif" alt="" align="bottom">');
+ }
geo_position_js.getCurrentPosition(function(pos) {
- $('#geolocate_para img').remove();
+ $link.find('img').remove();
var latitude = pos.coords.latitude;
var longitude = pos.coords.longitude;
location.href = '/around?latitude=' + latitude + ';longitude=' + longitude;
}, function(err) {
- $('#geolocate_para img').remove();
+ $link.find('img').remove();
if (err.code == 1) { // User said no
+ $link.html("You declined; please fill in the box above");
} else if (err.code == 2) { // No position
- $('#geolocate_para').html("Could not look up location");
+ $link.html("Could not look up location");
} else if (err.code == 3) { // Too long
- $('#geolocate_para').html("No result returned");
+ $link.html("No result returned");
} else { // Unknown
- $('#geolocate_para').html("Unknown error");
+ $link.html("Unknown error");
}
}, {
+ enableHighAccuracy: true,
timeout: 10000
});
});
}
+ // Delegation is necessary because #form_category may be replaced during the lifetime of the page
+ $("#problem_form").on("change.category", "select#form_category", function(){
+ var args = {
+ category: $(this).val()
+ };
+
+ if ( typeof fixmystreet !== 'undefined' ) {
+ args.latitude = fixmystreet.latitude;
+ args.longitude = fixmystreet.longitude;
+ } else {
+ args.latitude = $('input[name="latitude"]').val();
+ args.longitude = $('input[name="longitude"]').val();
+ }
+
+ $.getJSON('/report/new/category_extras', args, function(data) {
+ var $category_meta = $('#category_meta');
+ if ( data.category_extra ) {
+ if ( $category_meta.length ) {
+ $category_meta.html( data.category_extra );
+ } else {
+ $('#form_category_row').after( data.category_extra );
+ }
+ } else {
+ $category_meta.empty();
+ }
+ });
+ });
+
});
+
+})(jQuery);
+
diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js
index 1574754c9..9d8974fb6 100644
--- a/web/js/map-OpenLayers.js
+++ b/web/js/map-OpenLayers.js
@@ -236,8 +236,9 @@ $(function(){
if (fixmystreet.state_map && fixmystreet.state_map == 'full') {
// TODO Work better with window resizing, this is pretty 'set up' only at present
- var $content = $('.content'),
- q = ( $content.offset().left + $content.width() ) / 2;
+ var $content = $('.content'), mb = $('#map_box'),
+ q = ( $content.offset().left - mb.offset().left + $content.width() ) / 2;
+ if (q < 0) { q = 0; }
// Need to try and fake the 'centre' being 75% from the left
fixmystreet.map.pan(-q, -25, { animate: false });
fixmystreet.map.events.register("movestart", null, function(e){
@@ -441,6 +442,11 @@ OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
}
$('#councils_text').html(data.councils_text);
$('#form_category_row').html(data.category);
+ if ( data.extra_name_info ) {
+ // there might be a first name field on some cobrands
+ var lb = $('#form_first_name').prev() || $('#form_name').prev();
+ lb.before(data.extra_name_info);
+ }
});
$('#side-form, #site-logo').show();
@@ -474,7 +480,11 @@ OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
fixmystreet.map.getProjectionObject()
);
var p = fixmystreet.map.getViewPortPxFromLonLat(lonlat);
+<<<<<<< HEAD
+ p.x -= ( o.left - bo.left + w ) / 2;
+=======
p.x -= ( o.left + w ) / 2;
+>>>>>>> send-report-rewrite
lonlat = fixmystreet.map.getLonLatFromViewPortPx(p);
fixmystreet.map.panTo(lonlat);
}
diff --git a/web/js/modernizr.custom.76759.js b/web/js/modernizr.custom.76759.js
deleted file mode 100644
index 20a22d8fa..000000000
--- a/web/js/modernizr.custom.76759.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Modernizr 2.5.3 (Custom Build) | MIT & BSD
- * Build: http://www.modernizr.com/download/#-input-shiv-mq-teststyles-load
- */
-;window.Modernizr=function(a,b,c){function v(a){i.cssText=a}function w(a,b){return v(prefixes.join(a+";")+(b||""))}function x(a,b){return typeof a===b}function y(a,b){return!!~(""+a).indexOf(b)}function z(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:x(f,"function")?f.bind(d||b):f}return!1}function A(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)n[c[d]]=c[d]in j;return n.list&&(n.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),n}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" "))}var d="2.5.3",e={},f=b.documentElement,g="modernizr",h=b.createElement(g),i=h.style,j=b.createElement("input"),k={}.toString,l={},m={},n={},o=[],p=o.slice,q,r=function(a,c,d,e){var h,i,j,k=b.createElement("div"),l=b.body,m=l?l:b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:g+(d+1),k.appendChild(j);return h=["&#173;","<style>",a,"</style>"].join(""),k.id=g,m.innerHTML+=h,m.appendChild(k),l||(m.style.background="",f.appendChild(m)),i=c(k,a),l?k.parentNode.removeChild(k):m.parentNode.removeChild(m),!!i},s=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return r("@media "+b+" { #"+g+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},t={}.hasOwnProperty,u;!x(t,"undefined")&&!x(t.call,"undefined")?u=function(a,b){return t.call(a,b)}:u=function(a,b){return b in a&&x(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=p.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(p.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(p.call(arguments)))};return e});for(var B in l)u(l,B)&&(q=B.toLowerCase(),e[q]=l[B](),o.push((e[q]?"":"no-")+q));return e.input||A(),v(""),h=j=null,function(a,b){function g(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="<xyz></xyz>",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,e.mq=s,e.testStyles=r,e}(this,this.document),function(a,b,c){function d(a){return o.call(a)=="[object Function]"}function e(a){return typeof a=="string"}function f(){}function g(a){return!a||a=="loaded"||a=="complete"||a=="uninitialized"}function h(){var a=p.shift();q=1,a?a.t?m(function(){(a.t=="c"?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){a!="img"&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l={},o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};y[c]===1&&(r=1,y[c]=[],l=b.createElement(a)),a=="object"?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),a!="img"&&(r||y[c]===2?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i(b=="c"?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),p.length==1&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&o.call(a.opera)=="[object Opera]",l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return o.call(a)=="[object Array]"},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,i){var j=b(a),l=j.autoCallback;j.url.split(".").pop().split("?").shift(),j.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]||h),j.instead?j.instead(a,e,f,g,i):(y[j.url]?j.noexec=!0:y[j.url]=1,f.load(j.url,j.forceCSS||!j.forceJS&&"css"==j.url.split(".").pop().split("?").shift()?"c":c,j.noexec,j.attrs,j.timeout),(d(e)||d(l))&&f.load(function(){k(),e&&e(j.origUrl,i,g),l&&l(j.origUrl,i,g),y[j.url]=2})))}function i(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var j,l,m=this.yepnope.loader;if(e(a))g(a,0,m,0);else if(w(a))for(j=0;j<a.length;j++)l=a[j],e(l)?g(l,0,m,0):w(l)?B(l):Object(l)===l&&i(l,m);else Object(a)===a&&i(a,m)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))}; \ No newline at end of file
diff --git a/web/js/modernizr.custom.js b/web/js/modernizr.custom.js
new file mode 100644
index 000000000..c4d6ffdfc
--- /dev/null
+++ b/web/js/modernizr.custom.js
@@ -0,0 +1,4 @@
+/* Modernizr 2.5.3 (Custom Build) | MIT & BSD
+ * Build: http://www.modernizr.com/download/#-shiv-load
+ */
+;window.Modernizr=function(a,b,c){function t(a){i.cssText=a}function u(a,b){return t(prefixes.join(a+";")+(b||""))}function v(a,b){return typeof a===b}function w(a,b){return!!~(""+a).indexOf(b)}function x(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:v(f,"function")?f.bind(d||b):f}return!1}var d="2.5.3",e={},f=b.documentElement,g="modernizr",h=b.createElement(g),i=h.style,j,k={}.toString,l={},m={},n={},o=[],p=o.slice,q,r={}.hasOwnProperty,s;!v(r,"undefined")&&!v(r.call,"undefined")?s=function(a,b){return r.call(a,b)}:s=function(a,b){return b in a&&v(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=p.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(p.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(p.call(arguments)))};return e});for(var y in l)s(l,y)&&(q=y.toLowerCase(),e[q]=l[y](),o.push((e[q]?"":"no-")+q));return t(""),h=j=null,function(a,b){function g(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="<xyz></xyz>",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,e}(this,this.document),function(a,b,c){function d(a){return o.call(a)=="[object Function]"}function e(a){return typeof a=="string"}function f(){}function g(a){return!a||a=="loaded"||a=="complete"||a=="uninitialized"}function h(){var a=p.shift();q=1,a?a.t?m(function(){(a.t=="c"?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){a!="img"&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l={},o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};y[c]===1&&(r=1,y[c]=[],l=b.createElement(a)),a=="object"?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),a!="img"&&(r||y[c]===2?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i(b=="c"?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),p.length==1&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&o.call(a.opera)=="[object Opera]",l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return o.call(a)=="[object Array]"},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,i){var j=b(a),l=j.autoCallback;j.url.split(".").pop().split("?").shift(),j.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]||h),j.instead?j.instead(a,e,f,g,i):(y[j.url]?j.noexec=!0:y[j.url]=1,f.load(j.url,j.forceCSS||!j.forceJS&&"css"==j.url.split(".").pop().split("?").shift()?"c":c,j.noexec,j.attrs,j.timeout),(d(e)||d(l))&&f.load(function(){k(),e&&e(j.origUrl,i,g),l&&l(j.origUrl,i,g),y[j.url]=2})))}function i(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var j,l,m=this.yepnope.loader;if(e(a))g(a,0,m,0);else if(w(a))for(j=0;j<a.length;j++)l=a[j],e(l)?g(l,0,m,0):w(l)?B(l):Object(l)===l&&i(l,m);else Object(a)===a&&i(a,m)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))}; \ No newline at end of file