aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rwxr-xr-xweb/ajax.cgi6
-rwxr-xr-xweb/alert.cgi168
-rw-r--r--web/cobrands/barnet/css/layout.css8
-rw-r--r--web/cobrands/fiksgatami/css.css148
-rw-r--r--web/cobrands/fiksgatami/css.scss41
-rw-r--r--web/cobrands/southampton/SCClogo.pngbin0 -> 2698 bytes
-rw-r--r--web/cobrands/southampton/accessInfo.gifbin0 -> 2537 bytes
-rw-r--r--web/cobrands/southampton/bg-box.gifbin0 -> 3009 bytes
-rw-r--r--web/cobrands/southampton/bg-button.gifbin0 -> 53 bytes
-rw-r--r--web/cobrands/southampton/bg-footer.gifbin0 -> 664 bytes
-rw-r--r--web/cobrands/southampton/bg-header.jpgbin0 -> 33045 bytes
-rw-r--r--web/cobrands/southampton/bg-input.gifbin0 -> 66 bytes
-rw-r--r--web/cobrands/southampton/bg-repeat.gifbin0 -> 94 bytes
-rw-r--r--web/cobrands/southampton/blue-line.gifbin0 -> 54 bytes
-rw-r--r--web/cobrands/southampton/bullet.gifbin0 -> 118 bytes
-rw-r--r--web/cobrands/southampton/bulletActiveSG.gifbin0 -> 109 bytes
-rw-r--r--web/cobrands/southampton/css.css47
-rw-r--r--web/cobrands/southampton/css.scss67
-rw-r--r--web/cobrands/southampton/ff.pngbin0 -> 267194 bytes
-rw-r--r--web/cobrands/southampton/forms.pngbin0 -> 303561 bytes
-rw-r--r--web/cobrands/southampton/ie6.pngbin0 -> 199421 bytes
-rw-r--r--web/cobrands/southampton/information.gifbin0 -> 1025 bytes
-rw-r--r--web/cobrands/southampton/line.gifbin0 -> 54 bytes
-rw-r--r--web/cobrands/southampton/logo.pngbin0 -> 1885 bytes
-rw-r--r--web/cobrands/southampton/mctv.pngbin0 -> 3182 bytes
-rw-r--r--web/cobrands/southampton/safari.pngbin0 -> 318409 bytes
-rw-r--r--web/cobrands/southampton/style.css87
-rwxr-xr-xweb/confirm.cgi2
-rwxr-xr-xweb/contact.cgi11
-rw-r--r--web/css/_main.scss135
-rw-r--r--web/css/cobrands/emptyhomes/emptyhomes.css4
-rw-r--r--web/css/core.css850
-rw-r--r--web/css/core.scss507
-rw-r--r--web/css/ie6-378.css2
-rw-r--r--web/css/ie6.css2
-rw-r--r--web/css/main.css178
-rw-r--r--web/css/main.scss14
-rw-r--r--web/down.default.html2
-rwxr-xr-xweb/faq.cgi12
-rwxr-xr-xweb/import.cgi44
-rwxr-xr-xweb/index.cgi408
-rw-r--r--web/js.js8
-rw-r--r--web/js/map-OpenLayers.js182
-rw-r--r--web/js/map-OpenStreetMap.js34
-rw-r--r--web/js/map-bing-ol.js41
-rw-r--r--web/js/map-bing.js3
-rw-r--r--web/js/map-google.js2
-rw-r--r--web/js/map-streetview.js34
-rw-r--r--web/js/map-tilma-ol.js33
-rw-r--r--web/js/map-tilma.js2
-rwxr-xr-xweb/photo.cgi2
-rwxr-xr-xweb/questionnaire.cgi23
-rwxr-xr-xweb/reports.cgi127
-rwxr-xr-xweb/rss.cgi75
-rwxr-xr-xweb/tms-signup.cgi2
-rw-r--r--web/xsl.eha.xsl2
-rw-r--r--web/xsl.xsl2
57 files changed, 2322 insertions, 993 deletions
diff --git a/web/ajax.cgi b/web/ajax.cgi
index 69c389765..f13529852 100755
--- a/web/ajax.cgi
+++ b/web/ajax.cgi
@@ -59,8 +59,8 @@ sub main {
$list = '';
foreach (@$around_map) {
- my $dist = int($_->{distance}/100+.5)/10;
- $link = Cobrand::url($cobrand, NewURL($q, -retain => 1,
+ my $dist = int($_->{distance}*10+.5)/10;
+ $link = Cobrand::url($cobrand, NewURL($q, -retain => 1,
-url => '/report/' . $_->{id},
pc => undef,
x => undef,
@@ -81,7 +81,7 @@ sub main {
#$list = '';
#foreach (@$fixed) {
# $list .= '<li><a href="/report/' . $_->{id} . '">';
- # $list .= $_->{title} . ' <small>(' . int($_->{distance}/100+.5)/10 . 'km)</small>';
+ # $list .= $_->{title} . ' <small>(' . int($_->{distance}*10+.5)/10 . 'km)</small>';
# $list .= '</a></li>';
#}
#my $f_list = $list;
diff --git a/web/alert.cgi b/web/alert.cgi
index 71249759e..fd30dbf4e 100755
--- a/web/alert.cgi
+++ b/web/alert.cgi
@@ -11,6 +11,7 @@
use strict;
use Standard;
use Digest::SHA1 qw(sha1_hex);
+use Encode;
use Error qw(:try);
use CrossSell;
use FixMyStreet::Alert;
@@ -24,6 +25,7 @@ use mySociety::MaPit;
use mySociety::VotingArea;
use mySociety::Web qw(ent);
use Cobrand;
+use Utils;
sub main {
my $q = shift;
@@ -56,7 +58,7 @@ EOF
} elsif ($q->param('type') && $q->param('feed')) {
$title = _('Local RSS feeds and email alerts');
$out = alert_local_form($q);
- } elsif ($q->param('pc') || ($q->param('e') && $q->param('n'))) {
+ } elsif ($q->param('pc') || ($q->param('lat') || $q->param('lon'))) {
$title = _('Local RSS feeds and email alerts');
$out = alert_list($q);
} else {
@@ -72,47 +74,99 @@ Page::do_fastcgi(\&main);
sub alert_list {
my ($q, @errors) = @_;
- my @vars = qw(pc rznvy e n);
+ my @vars = qw(pc rznvy lat lon);
my %input = map { $_ => scalar $q->param($_) } @vars;
my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
- my($error, $e, $n);
- if ($input{e} || $input{n}) {
- $e = $input{e};
- $n = $input{n};
+ my($error, $lat, $lon);
+ if ($input{lat} || $input{lon}) {
+ $lat = $input{lat};
+ $lon = $input{lon};
} else {
try {
- ($e, $n, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
+ ($lat, $lon, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
} catch Error::Simple with {
$error = shift;
};
}
+
return FixMyStreet::Geocode::list_choices($error, '/alert', $q) if ref($error) eq 'ARRAY';
return alert_front_page($q, $error) if $error;
my $pretty_pc = $input_h{pc};
+ my $pretty_pc_text;# This one isnt't getting the nbsp.
if (mySociety::PostcodeUtil::is_valid_postcode($input{pc})) {
$pretty_pc = mySociety::PostcodeUtil::canonicalise_postcode($input{pc});
+ $pretty_pc_text = $pretty_pc;
+ $pretty_pc_text =~ s/ //g;
$pretty_pc =~ s/ /&nbsp;/;
}
+ # truncate the lat,lon for nicer urls
+ ( $lat, $lon ) = map { Utils::truncate_coordinate($_) } ( $lat, $lon );
+
my $errors = '';
$errors = '<ul class="error"><li>' . join('</li><li>', @errors) . '</li></ul>' if @errors;
- my @types = (@$mySociety::VotingArea::council_parent_types, @$mySociety::VotingArea::council_child_types);
- my %councils = map { $_ => 1 } @$mySociety::VotingArea::council_parent_types;
-
- my $areas = mySociety::MaPit::call('point', "27700/$e,$n", type => \@types);
my $cobrand = Page::get_cobrand($q);
+ my @types = (Cobrand::area_types($cobrand), @$mySociety::VotingArea::council_child_types);
+ my %councils = map { $_ => 1 } Cobrand::area_types($cobrand);
+
+ my $areas = mySociety::MaPit::call('point', "4326/$lon,$lat", type => \@types);
my ($success, $error_msg) = Cobrand::council_check($cobrand, { all_councils => $areas }, $q, 'alert');
- if (!$success){
+ if (!$success) {
return alert_front_page($q, $error_msg);
}
return alert_front_page($q, _('That location does not appear to be covered by a council, perhaps it is offshore - please try somewhere more specific.')) if keys %$areas == 0;
my ($options, $options_start, $options_end);
- if (keys %$areas == 2) {
+ if (mySociety::Config::get('COUNTRY') eq 'NO') {
+
+ my (@options, $fylke, $kommune);
+ foreach (values %$areas) {
+ if ($_->{type} eq 'NKO') {
+ $kommune = $_;
+ } else {
+ $fylke = $_;
+ }
+ }
+ my $kommune_name = $kommune->{name};
+ my $fylke_name = $fylke->{name};
+
+ if ($fylke->{id} == 3) { # Oslo
+
+ push @options, [ 'council', $fylke->{id}, Page::short_name($fylke),
+ sprintf(_("Problems within %s"), $fylke_name) ];
+
+ $options_start = "<div><ul id='rss_feed'>";
+ $options = alert_list_options($q, @options);
+ $options_end = "</ul>";
+
+ } else {
+
+ push @options,
+ [ 'area', $kommune->{id}, Page::short_name($kommune), $kommune_name ],
+ [ 'area', $fylke->{id}, Page::short_name($fylke), $fylke_name ];
+ $options_start = '<div id="rss_list">';
+ $options = $q->p($q->strong(_('Problems within the boundary of:'))) .
+ $q->ul(alert_list_options($q, @options));
+ @options = ();
+ push @options,
+ [ 'council', $kommune->{id}, Page::short_name($kommune), $kommune_name ],
+ [ 'council', $fylke->{id}, Page::short_name($fylke), $fylke_name ];
+ $options .= $q->p($q->strong(_('Or problems reported to:'))) .
+ $q->ul(alert_list_options($q, @options));
+ $options_end = $q->p($q->small(_('FixMyStreet sends different categories of problem
+to the appropriate council, so problems within the boundary of a particular council
+might not match the problems sent to that council. For example, a graffiti report
+will be sent to the district council, so will appear in both of the district
+council&rsquo;s alerts, but will only appear in the "Within the boundary" alert
+for the county council.'))) . '</div><div id="rss_buttons">';
+
+ }
+
+ } elsif (keys %$areas == 2) {
# One-tier council
my (@options, $council, $ward);
@@ -123,10 +177,12 @@ sub alert_list {
$ward = $_;
}
}
- push @options, [ 'council', $council->{id}, Page::short_name($council->{name}),
- sprintf(_("Problems within %s"), $council->{name}) ];
- push @options, [ 'ward', $council->{id}.':'.$ward->{id}, Page::short_name($council->{name}) . '/'
- . Page::short_name($ward->{name}), sprintf(_("Problems within %s ward"), $ward->{name}) ];
+ my $council_name = $council->{name};
+ my $ward_name = $ward->{name};
+ push @options, [ 'council', $council->{id}, Page::short_name($council),
+ sprintf(_("Problems within %s"), $council_name) ];
+ push @options, [ 'ward', $council->{id}.':'.$ward->{id}, Page::short_name($council) . '/'
+ . Page::short_name($ward), sprintf(_("Problems within %s ward"), $ward_name) ];
$options_start = "<div><ul id='rss_feed'>";
$options = alert_list_options($q, @options);
@@ -139,8 +195,9 @@ sub alert_list {
foreach (values %$areas) {
$council = $_;
}
- push @options, [ 'council', $council->{id}, Page::short_name($council->{name}),
- sprintf(_("Problems within %s"), $council->{name}) ];
+ my $council_name = $council->{name};
+ push @options, [ 'council', $council->{id}, Page::short_name($council),
+ sprintf(_("Problems within %s"), $council_name) ];
$options_start = "<div><ul id='rss_feed'>";
$options = alert_list_options($q, @options);
@@ -161,26 +218,30 @@ sub alert_list {
$d_ward = $_;
}
}
+ my $district_name = $district->{name};
+ my $d_ward_name = $d_ward->{name};
+ my $county_name = $county->{name};
+ my $c_ward_name = $c_ward->{name};
push @options,
- [ 'area', $district->{id}, Page::short_name($district->{name}), $district->{name} ],
- [ 'area', $district->{id}.':'.$d_ward->{id}, Page::short_name($district->{name}) . '/'
- . Page::short_name($d_ward->{name}), "$d_ward->{name} ward, $district->{name}" ],
- [ 'area', $county->{id}, Page::short_name($county->{name}), $county->{name} ],
- [ 'area', $county->{id}.':'.$c_ward->{id}, Page::short_name($county->{name}) . '/'
- . Page::short_name($c_ward->{name}), "$c_ward->{name} ward, $county->{name}" ];
+ [ 'area', $district->{id}, Page::short_name($district), $district_name ],
+ [ 'area', $district->{id}.':'.$d_ward->{id}, Page::short_name($district) . '/'
+ . Page::short_name($d_ward), "$d_ward_name ward, $district_name" ],
+ [ 'area', $county->{id}, Page::short_name($county), $county_name ],
+ [ 'area', $county->{id}.':'.$c_ward->{id}, Page::short_name($county) . '/'
+ . Page::short_name($c_ward), "$c_ward_name ward, $county_name" ];
$options_start = '<div id="rss_list">';
$options = $q->p($q->strong(_('Problems within the boundary of:'))) .
$q->ul(alert_list_options($q, @options));
@options = ();
push @options,
- [ 'council', $district->{id}, Page::short_name($district->{name}), $district->{name} ],
- [ 'ward', $district->{id}.':'.$d_ward->{id}, Page::short_name($district->{name}) . '/' . Page::short_name($d_ward->{name}),
- "$district->{name}, within $d_ward->{name} ward" ];
+ [ 'council', $district->{id}, Page::short_name($district), $district_name ],
+ [ 'ward', $district->{id}.':'.$d_ward->{id}, Page::short_name($district) . '/' . Page::short_name($d_ward),
+ "$district_name, within $d_ward_name ward" ];
if ($q->{site} ne 'emptyhomes') {
push @options,
- [ 'council', $county->{id}, Page::short_name($county->{name}), $county->{name} ],
- [ 'ward', $county->{id}.':'.$c_ward->{id}, Page::short_name($county->{name}) . '/'
- . Page::short_name($c_ward->{name}), "$county->{name}, within $c_ward->{name} ward" ];
+ [ 'council', $county->{id}, Page::short_name($county), $county_name ],
+ [ 'ward', $county->{id}.':'.$c_ward->{id}, Page::short_name($county) . '/'
+ . Page::short_name($c_ward), "$county_name, within $c_ward_name ward" ];
$options .= $q->p($q->strong(_('Or problems reported to:'))) .
$q->ul(alert_list_options($q, @options));
$options_end = $q->p($q->small(_('FixMyStreet sends different categories of problem
@@ -194,18 +255,17 @@ for the county council.'))) . '</div><div id="rss_buttons">';
}
} else {
# Hopefully impossible in the UK!
- throw Error::Simple('An area with three tiers of council? Impossible! '. $e . ' ' . $n . ' ' . join('|',keys %$areas));
+ throw Error::Simple('An area with three tiers of council? Impossible! '. $lat . ' ' . $lon . ' ' . join('|',keys %$areas));
}
- my ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($e, $n, 'G');
my $dist = mySociety::Gaze::get_radius_containing_population($lat, $lon, 200000);
$dist = int($dist * 10 + 0.5);
$dist = $dist / 10.0;
my $checked = '';
- $checked = ' checked' if $q->param('feed') && $q->param('feed') eq "local:$e:$n";
+ $checked = ' checked' if $q->param('feed') && $q->param('feed') eq "local:$lat:$lon";
my $cobrand_form_elements = Cobrand::form_elements($cobrand, 'alerts', $q);
- my $pics = Cobrand::recent_photos($cobrand, 5, $e, $n, $dist);
+ my $pics = Cobrand::recent_photos($cobrand, 5, $lat, $lon, $dist);
$pics = '<div id="alert_photos">' . $q->h2(_('Photos of recent nearby reports')) . $pics . '</div>' if $pics;
my $header;
if ($pretty_pc) {
@@ -231,20 +291,26 @@ feed, or enter your email address to subscribe to an email alert.'));
my $rss_label = sprintf(_('Problems within %skm of this location'), $dist);
$out .= <<EOF;
<p id="rss_local">
-<input type="radio" name="feed" id="local:$e:$n" value="local:$e:$n"$checked>
-<label for="local:$e:$n">$rss_label</label>
+<input type="radio" name="feed" id="local:$lat:$lon" value="local:$lat:$lon"$checked>
+<label for="local:$lat:$lon">$rss_label</label>
EOF
- my $rss_feed = Cobrand::url($cobrand, "/rss/n/$e,$n", $q);
- my $default_link = Cobrand::url($cobrand, "/alert?type=local;feed=local:$e:$n", $q);
+ my $rss_feed;
+ if ($pretty_pc_text) {
+ $rss_feed = Cobrand::url($cobrand, "/rss/pc/$pretty_pc_text", $q);
+ } else {
+ $rss_feed = Cobrand::url($cobrand, "/rss/l/$lat,$lon", $q);
+ }
+
+ my $default_link = Cobrand::url($cobrand, "/alert?type=local;feed=local:$lat:$lon", $q);
my $rss_details = _('(a default distance which covers roughly 200,000 people)');
$out .= $rss_details;
$out .= " <a href='$rss_feed'><img src='/i/feed.png' width='16' height='16' title='"
. _('RSS feed of nearby problems') . "' alt='" . _('RSS feed') . "' border='0'></a>";
$out .= '</p> <p id="rss_local_alt">' . _('(alternatively the RSS feed can be customised, within');
- my $rss_feed_2k = Cobrand::url($cobrand, "/rss/n/$e,$n/2", $q);
- my $rss_feed_5k = Cobrand::url($cobrand, "/rss/n/$e,$n/5", $q);
- my $rss_feed_10k = Cobrand::url($cobrand, "/rss/n/$e,$n/10", $q);
- my $rss_feed_20k = Cobrand::url($cobrand, "/rss/n/$e,$n/20", $q);
+ my $rss_feed_2k = Cobrand::url($cobrand, $rss_feed.'/2', $q);
+ my $rss_feed_5k = Cobrand::url($cobrand, $rss_feed.'/5', $q);
+ my $rss_feed_10k = Cobrand::url($cobrand, $rss_feed.'/10', $q);
+ my $rss_feed_20k = Cobrand::url($cobrand, $rss_feed.'/20', $q);
$out .= <<EOF;
<a href="$rss_feed_2k">2km</a> / <a href="$rss_feed_5k">5km</a>
/ <a href="$rss_feed_10k">10km</a> / <a href="$rss_feed_20k">20km</a>)
@@ -271,8 +337,8 @@ EOF
rss_feed_5k => $rss_feed_5k,
rss_feed_10k => $rss_feed_10k,
rss_feed_20k => $rss_feed_20k,
- e => $e,
- n => $n,
+ lat => $lat,
+ lon => $lon,
options => $options );
my $cobrand_page = Page::template_include('alert-options', $q, Page::template_root($q), %vars);
$out = $cobrand_page if ($cobrand_page);
@@ -371,8 +437,8 @@ sub alert_rss {
$url .= "?" . $extra_params if ($extra_params);
print $q->redirect($url);
return;
- } elsif ($feed =~ /^local:(\d+):(\d+)$/) {
- $url = $base_url . '/rss/n/' . $1 . ',' . $2;
+ } elsif ($feed =~ /^local:([\d\.-]+):([\d\.-]+)$/) {
+ $url = $base_url . '/rss/l/' . $1 . ',' . $2;
$url .= "?" . $extra_params if ($extra_params);
print $q->redirect($url);
return;
@@ -526,8 +592,10 @@ sub alert_do_subscribe {
$alert_id = FixMyStreet::Alert::create($email, 'council_problems', $cobrand, $cobrand_data, $1, $1);
} elsif ($feed =~ /^ward:(\d+):(\d+)/) {
$alert_id = FixMyStreet::Alert::create($email, 'ward_problems', $cobrand, $cobrand_data, $1, $2);
- } elsif ($feed =~ /^local:(\d+):(\d+)/) {
- $alert_id = FixMyStreet::Alert::create($email, 'local_problems', $cobrand, $cobrand_data, $1, $2);
+ } elsif ($feed =~ m{ \A local: ( [\+\-]? \d+ \.? \d* ) : ( [\+\-]? \d+ \.? \d* ) }xms ) {
+ my $lat = $1;
+ my $lon = $2;
+ $alert_id = FixMyStreet::Alert::create($email, 'local_problems', $cobrand, $cobrand_data, $lon, $lat);
}
} else {
throw FixMyStreet::Alert::Error('Invalid type');
@@ -537,6 +605,6 @@ sub alert_do_subscribe {
$h{url} = Page::base_url_with_lang($q, undef, 1) . '/A/'
. mySociety::AuthToken::store('alert', { id => $alert_id, type => 'subscribe', email => $email } );
dbh()->commit();
- return Page::send_email($q, $email, undef, 'alert', %h);
+ return Page::send_confirmation_email($q, $email, undef, 'alert', %h);
}
diff --git a/web/cobrands/barnet/css/layout.css b/web/cobrands/barnet/css/layout.css
index b66f957b6..1445ff419 100644
--- a/web/cobrands/barnet/css/layout.css
+++ b/web/cobrands/barnet/css/layout.css
@@ -1,13 +1,13 @@
/* FixMyStreet additions */
/* Smaller map */
-#map_box {
+#mysociety #map_box {
width: 380px;
}
-#map, #drag {
+#mysociety #map, #mysociety #drag {
width: 378px;
height: 378px;
}
-#watermark {
+#mysociety #watermark {
background: url("/i/mojwatermark-378.png");
height: 84px;
width: 171px;
@@ -16,7 +16,7 @@
right: 0;
}
-p#fixed, p#unknown {
+#mysociety p#fixed, #mysociety p#unknown {
margin-right: 400px;
width: auto;
}
diff --git a/web/cobrands/fiksgatami/css.css b/web/cobrands/fiksgatami/css.css
new file mode 100644
index 000000000..8de8de1fe
--- /dev/null
+++ b/web/cobrands/fiksgatami/css.css
@@ -0,0 +1,148 @@
+#mysociety #front_stats div {
+ width: 6.5em;
+}
+#mysociety label {
+ width: 6em;
+}
+#mysociety #fieldset div.checkbox, #mysociety #problem_submit {
+ padding-left: 6.5em;
+}
+
+body {
+ font-family: "Gill Sans", "Gill Sans MT", Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+}
+
+h1 {
+ margin: 0;
+ font-size: 175%;
+}
+
+h2 {
+ font-size: 140%;
+}
+
+select, input, textarea {
+ font-size: 99%;
+}
+
+#mysociety a.unsuitable-report {
+ font-size: small;
+}
+#mysociety blockquote {
+ border-left: solid 4px #1a4f7f;
+}
+#mysociety .a {
+ color: #000000;
+ background-color: #a9cff1;
+}
+#mysociety #postcodeForm {
+ background-color: #99bfe1;
+}
+#mysociety #front_stats div {
+ background-color: #99bfe1;
+}
+
+#header {
+ font-size: 200%;
+ font-weight: bold;
+ border-bottom: solid 2px #1a4f7f;
+ margin: 0;
+ padding: 0.15em 0.5em;
+ background-color: #99bfe1;
+ color: #1a4f7f;
+}
+#header a:link, #header a:visited {
+ color: #1a4f7f;
+ background-color: #99bfe1;
+ text-decoration: none;
+}
+#header a:active, #header a:hover {
+ text-decoration: underline;
+}
+
+#my {
+ color: #0a3f6f;
+ background-color: #99bfe1;
+}
+
+#mysociety {
+ width: 100%;
+ /* Must specify a width or IE goes crazy wrong! */
+ position: relative;
+ margin: 0 auto;
+ max-width: 60em;
+}
+
+/* Can't put the margin in #mysociety because of above IE craziness */
+#wrapper {
+ margin: 2em;
+}
+
+#navigation {
+ position: absolute;
+ top: 1em;
+ right: 1em;
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+}
+#navigation li {
+ display: inline;
+ padding: 0;
+ margin: 0;
+}
+#navigation a {
+ display: -moz-inline-box;
+ display: inline-block;
+ padding: 0.4em 1em;
+}
+#navigation a:link, #navigation a:visited {
+ color: #1a4f7f;
+}
+#navigation a:hover, #navigation a:active {
+ background-color: #1a4f7f;
+ color: #99bfe1;
+}
+
+#nav_new a {
+ background-image: url("/i/new.png");
+ background-repeat: no-repeat;
+ background-position: 100% 0;
+}
+
+#logo {
+ border: none;
+ position: absolute;
+ top: 3.3em;
+ right: 10px;
+}
+
+#footer {
+ clear: both;
+ text-align: right;
+ font-size: 83%;
+ border-top: solid 1px #1a4f7f;
+ display: table;
+ margin: 2em 0 1em auto;
+ padding: 2px 4px;
+}
+
+body {
+ font-family: Helmet, Freesans, "Helvetica Neue", Arial, sans-serif;
+}
+
+a:link {
+ color: #215d93;
+}
+a:visited {
+ color: #518dc3;
+}
+a:hover, a:active {
+ color: #cc0000;
+}
+
+#header {
+ padding: 0.1em 0.5em 0.15em;
+}
diff --git a/web/cobrands/fiksgatami/css.scss b/web/cobrands/fiksgatami/css.scss
new file mode 100644
index 000000000..aa09b024a
--- /dev/null
+++ b/web/cobrands/fiksgatami/css.scss
@@ -0,0 +1,41 @@
+$header_back: #99bfe1;
+$header_back_lighter: #a9cff1;
+$header_colour: #1a4f7f;
+$header_darker: #0a3f6f;
+
+// Overrides of core.css
+
+#mysociety {
+
+ #front_stats div {
+ width: 6.5em;
+ }
+
+ label {
+ width: 6em;
+ }
+
+ #fieldset div.checkbox, #problem_submit {
+ padding-left: 6.5em;
+ }
+
+}
+
+@import "../../css/_main";
+
+// Overrides of main.css
+
+body {
+ font-family: Helmet, Freesans, "Helvetica Neue", Arial, sans-serif;
+}
+
+a {
+ &:link { color: #215d93; }
+ &:visited { color: #518dc3; }
+ &:hover, &:active { color: #cc0000; }
+}
+
+#header {
+ padding: 0.1em 0.5em 0.15em;
+}
+
diff --git a/web/cobrands/southampton/SCClogo.png b/web/cobrands/southampton/SCClogo.png
new file mode 100644
index 000000000..74a037a8c
--- /dev/null
+++ b/web/cobrands/southampton/SCClogo.png
Binary files differ
diff --git a/web/cobrands/southampton/accessInfo.gif b/web/cobrands/southampton/accessInfo.gif
new file mode 100644
index 000000000..418698ed5
--- /dev/null
+++ b/web/cobrands/southampton/accessInfo.gif
Binary files differ
diff --git a/web/cobrands/southampton/bg-box.gif b/web/cobrands/southampton/bg-box.gif
new file mode 100644
index 000000000..559a5ae00
--- /dev/null
+++ b/web/cobrands/southampton/bg-box.gif
Binary files differ
diff --git a/web/cobrands/southampton/bg-button.gif b/web/cobrands/southampton/bg-button.gif
new file mode 100644
index 000000000..f5f8122dc
--- /dev/null
+++ b/web/cobrands/southampton/bg-button.gif
Binary files differ
diff --git a/web/cobrands/southampton/bg-footer.gif b/web/cobrands/southampton/bg-footer.gif
new file mode 100644
index 000000000..89919c1cd
--- /dev/null
+++ b/web/cobrands/southampton/bg-footer.gif
Binary files differ
diff --git a/web/cobrands/southampton/bg-header.jpg b/web/cobrands/southampton/bg-header.jpg
new file mode 100644
index 000000000..70e0ec46a
--- /dev/null
+++ b/web/cobrands/southampton/bg-header.jpg
Binary files differ
diff --git a/web/cobrands/southampton/bg-input.gif b/web/cobrands/southampton/bg-input.gif
new file mode 100644
index 000000000..267fe9b6b
--- /dev/null
+++ b/web/cobrands/southampton/bg-input.gif
Binary files differ
diff --git a/web/cobrands/southampton/bg-repeat.gif b/web/cobrands/southampton/bg-repeat.gif
new file mode 100644
index 000000000..b68346517
--- /dev/null
+++ b/web/cobrands/southampton/bg-repeat.gif
Binary files differ
diff --git a/web/cobrands/southampton/blue-line.gif b/web/cobrands/southampton/blue-line.gif
new file mode 100644
index 000000000..c7a587ee5
--- /dev/null
+++ b/web/cobrands/southampton/blue-line.gif
Binary files differ
diff --git a/web/cobrands/southampton/bullet.gif b/web/cobrands/southampton/bullet.gif
new file mode 100644
index 000000000..a86ef002b
--- /dev/null
+++ b/web/cobrands/southampton/bullet.gif
Binary files differ
diff --git a/web/cobrands/southampton/bulletActiveSG.gif b/web/cobrands/southampton/bulletActiveSG.gif
new file mode 100644
index 000000000..6f4e3e438
--- /dev/null
+++ b/web/cobrands/southampton/bulletActiveSG.gif
Binary files differ
diff --git a/web/cobrands/southampton/css.css b/web/cobrands/southampton/css.css
new file mode 100644
index 000000000..85f66dcc3
--- /dev/null
+++ b/web/cobrands/southampton/css.css
@@ -0,0 +1,47 @@
+#mysociety #map_box {
+ width: 380px;
+}
+#mysociety #map, #mysociety #drag {
+ width: 378px;
+ height: 378px;
+}
+#mysociety #watermark {
+ background: url("/i/mojwatermark-378.png");
+ height: 84px;
+ width: 171px;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+}
+#mysociety p#fixed, #mysociety p#unknown {
+ margin-right: 400px;
+ width: auto;
+}
+#mysociety h1 {
+ margin: 0;
+ font-size: 175%;
+}
+#mysociety h2 {
+ font-size: 140%;
+}
+#mysociety select, #mysociety input, #mysociety textarea {
+ font-size: 99%;
+}
+#mysociety a.unsuitable-report {
+ font-size: small;
+}
+#mysociety blockquote {
+ border-left: solid 4px #768eb5;
+}
+#mysociety .a {
+ color: #000000;
+ background-color: #e9eef7;
+}
+#mysociety #postcodeForm {
+ background-color: #e9eef7;
+}
+#mysociety #front_stats div {
+ background-color: #e9eef7;
+ width: 6em;
+ padding: 0.5em;
+}
diff --git a/web/cobrands/southampton/css.scss b/web/cobrands/southampton/css.scss
new file mode 100644
index 000000000..57cb95a8f
--- /dev/null
+++ b/web/cobrands/southampton/css.scss
@@ -0,0 +1,67 @@
+$map_width: 378px;
+$background: #E9EEF7;
+$darker: #768EB5;
+
+#mysociety {
+
+ // Smaller map
+
+ #map_box {
+ width: $map_width + 2px;
+ }
+ #map, #drag {
+ width: $map_width;
+ height: $map_width;
+ }
+ #watermark {
+ background: url("/i/mojwatermark-378.png");
+ height: 84px;
+ width: 171px;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ }
+
+ p#fixed, p#unknown {
+ margin-right: $map_width + 22px;
+ width: auto;
+ }
+
+ // Generics
+
+ h1 {
+ margin: 0;
+ font-size: 175%;
+ }
+ h2 {
+ font-size: 140%;
+ }
+
+ select, input, textarea {
+ font-size: 99%;
+ }
+
+ a.unsuitable-report {
+ font-size: small;
+ }
+
+ blockquote {
+ border-left: solid 4px $darker;
+ }
+
+ .a {
+ color: #000000;
+ background-color: $background;
+ }
+
+ #postcodeForm {
+ background-color: $background;
+ }
+
+ #front_stats div {
+ background-color: $background;
+ width: 6em;
+ padding: 0.5em;
+ }
+
+}
diff --git a/web/cobrands/southampton/ff.png b/web/cobrands/southampton/ff.png
new file mode 100644
index 000000000..ef7d91148
--- /dev/null
+++ b/web/cobrands/southampton/ff.png
Binary files differ
diff --git a/web/cobrands/southampton/forms.png b/web/cobrands/southampton/forms.png
new file mode 100644
index 000000000..4f278e9ae
--- /dev/null
+++ b/web/cobrands/southampton/forms.png
Binary files differ
diff --git a/web/cobrands/southampton/ie6.png b/web/cobrands/southampton/ie6.png
new file mode 100644
index 000000000..d6179fa02
--- /dev/null
+++ b/web/cobrands/southampton/ie6.png
Binary files differ
diff --git a/web/cobrands/southampton/information.gif b/web/cobrands/southampton/information.gif
new file mode 100644
index 000000000..ea2f14bd2
--- /dev/null
+++ b/web/cobrands/southampton/information.gif
Binary files differ
diff --git a/web/cobrands/southampton/line.gif b/web/cobrands/southampton/line.gif
new file mode 100644
index 000000000..fa6ddca0c
--- /dev/null
+++ b/web/cobrands/southampton/line.gif
Binary files differ
diff --git a/web/cobrands/southampton/logo.png b/web/cobrands/southampton/logo.png
new file mode 100644
index 000000000..71bdc9d97
--- /dev/null
+++ b/web/cobrands/southampton/logo.png
Binary files differ
diff --git a/web/cobrands/southampton/mctv.png b/web/cobrands/southampton/mctv.png
new file mode 100644
index 000000000..17f3ecec6
--- /dev/null
+++ b/web/cobrands/southampton/mctv.png
Binary files differ
diff --git a/web/cobrands/southampton/safari.png b/web/cobrands/southampton/safari.png
new file mode 100644
index 000000000..e99547a7f
--- /dev/null
+++ b/web/cobrands/southampton/safari.png
Binary files differ
diff --git a/web/cobrands/southampton/style.css b/web/cobrands/southampton/style.css
new file mode 100644
index 000000000..400859102
--- /dev/null
+++ b/web/cobrands/southampton/style.css
@@ -0,0 +1,87 @@
+body {font-family:Verdana, Geneva, sans-serif; font-size:62.5%;}
+
+a {text-decoration:none; color:#1c4384; font-weight:bold;}
+
+a:hover {text-decoration:underline;}
+
+p {margin:0 0 10px 0;}
+
+/* ******* Start of Header ******* */
+
+ul#topMenu {width:860px; height:15px; margin:13px auto 3px auto;}
+ul#topMenu li {float:left; list-style-type:none;}
+ul#topMenu a {padding:0 5px 2px 5px; font-size:0.9em; color:#000; font-weight:400;}
+
+#wrapper {width:960px; height:auto; margin:0 auto; background:url(bg-repeat.gif) repeat-y;}
+#header {width:100%; height:176px; background:url(bg-header.jpg) no-repeat; background-position:1px 0px;}
+#header .logo {float:left; width:87px; height:81px; margin:25px 0 17px 46px;}
+#header a.siteTitle {height:27px; width:287px; background:url(logo.png) no-repeat; display:block; font-family:verdana; float:left; margin:60px 0 0 15px; text-indent:-9999px;}
+
+a.mctv {float:right; height:37px; width:104px; margin:15px 7px 0 0;}
+a.mctv img {border:none;}
+
+#searchWrap {width:210px; height:auto; float:right; margin:10px 30px 0 0;}
+#searchWrap form {border:none; padding:0; margin:0 0 10px 0;}
+#searchWrap fieldset {border:none; padding:0; margin:0;}
+#searchWrap label {color:#1b4384; font-weight:700; font-size:1.1em; margin:0; padding:0;}
+#searchWrap input {float:left; background:url(bg-input.gif) repeat-x; margin:3px 0 0 0; line-height:16px; padding:3px 5px 3px 4px;}
+#searchWrap .button {background:url(bg-button.gif) repeat-x; margin:3px 0 0 5px; float:left; height:26px; padding:0 3px 4px 3px; color:#fff; border:none;}
+
+.moreInfo {margin:0 0 -2px 2px;}
+.text {width:109px; color:#999;}
+.text2 {width:137px; color:#999;}
+
+ul#topNav {width:870px; height:17px; background:#1b4384; clear:both; margin:0 auto; padding:3px 0 1px 0;}
+ul#topNav li {float:left; list-style-type:none; background:url(line.gif) no-repeat 0 2px;}
+ul#topNav li:first-child {background:none;}
+ul#topNav li a {color:#ffffff; font-size:1.2em; padding:0 7px 0 8px; font-size:1.2em; font-weight:400;}
+
+p.atoz {float:left; margin:8px 0 0 43px; padding:5px 5px 3px 0; font-size:1.2em; border-bottom:1px solid #E0DBEF;}
+ul#atoz {width:485px; float:left; margin:13px 0 0 0; border-bottom:1px solid #E0DBEF; padding:0 0 1px 0;}
+ul#atoz li {list-style-type:none; display:inline;}
+ul#atoz li a {font-size:13px; font-weight:400;}
+
+ul#contacts {float:right; margin:13px 36px 0 0; padding:0;}
+ul#contacts li {float:left; list-style-type:none; background:url(blue-line.gif) no-repeat 0 2px;}
+ul#contacts li:first-child {background:none;}
+ul#contacts li a {font-size:1.2em; padding:0 8px 0 10px; font-weight:400;}
+
+/* ******* End of Header ******* */
+
+
+
+/* ******* Start of Left Menu Bar ******* */
+
+#menuBar {width:200px; height:auto; float:left; margin:25px 0 0 43px; padding-bottom:25px;}
+
+ul#leftMenu {height:auto; width:199px; float:left; background:#e9eef7 url(bg-box.gif) no-repeat -1px 100%; padding:0 0 10px 0; margin:5px 0 0 0; overflow:hidden;}
+ul#leftMenu li {list-style-type:none; width:199px; padding:0;}
+ul#leftMenu li a {display:block; width:100%; line-height:1.5em; padding:3px 10px 3px 32px; font-size:1.2em; font-weight:700;}
+ul#leftMenu li.parent {background:url(bulletActiveSG.gif) no-repeat #768eb5; background-position:10px 11px; color:#fff; padding:3px 0 3px 0;}
+ul#leftMenu li.parent a {color:#fff}
+ul#leftMenu li.selected {background:url(bullet.gif) no-repeat; background-position:10px 8px; color:#fff; padding:0;}
+
+/* ******* End of Left Menu Bar ******* */
+
+
+
+/* ******* Start of Main Content Area ******* */
+
+#contentArea {width:640px; height:auto; float:left; padding-bottom:25px; font-size:1.1em; margin:15px 0 0 0; padding:15px 0 20px 25px;}
+
+/* ******* End of Main Content Area ******* */
+
+
+
+/* ******* Start of Footer ******* */
+
+#footer {width:100%; height:54px; clear:both; background:url(bg-footer.gif) no-repeat;}
+
+a.accessInfo {float:left; height:32px; width:117px; margin:0 10px 0 43px;}
+a.accessInfo img {border:none;}
+
+ul#bottomMenu {float:left; margin:10px 0 0 10px;}
+ul#bottomMenu li {float:left; list-style-type:none;}
+ul#bottomMenu a {padding:0 4px 2px 4px; font-size:0.9em; color:#000; font-weight:400;}
+
+/* ******* End of Footer ******* */
diff --git a/web/confirm.cgi b/web/confirm.cgi
index a16f8fb93..c4a37c67f 100755
--- a/web/confirm.cgi
+++ b/web/confirm.cgi
@@ -192,7 +192,7 @@ sub ask_questionnaire {
my $qn_thanks = _("Thanks, glad to hear it's been fixed! Could we just ask if you have ever reported a problem to a council before?");
my $yes = _('Yes');
my $no = _('No');
- my $go = _('Go');
+ my $go = _('Submit');
my $form_action = Cobrand::url($cobrand, "/confirm", $q);
my $form_extra_elements = Cobrand::form_elements($cobrand, 'questionnaire', $q);
my $out = <<EOF;
diff --git a/web/contact.cgi b/web/contact.cgi
index fd0043d94..aefd3de7a 100755
--- a/web/contact.cgi
+++ b/web/contact.cgi
@@ -106,6 +106,8 @@ sub contact_details {
my $out = '';
my $sitename = _('FixMyStreet');
my $contact_info = '';
+ if ( mySociety::Config::get('COUNTRY') eq 'GB' ) {
+ # XXX Rewrite to make brandable?
$contact_info .= <<EOF;
<div class="contact-details">
<p>$sitename is a service provided by mySociety, which is the project of a
@@ -120,6 +122,7 @@ UK</p>
</div>
EOF
$out .= $contact_info unless $q->{site} eq 'emptyhomes';
+ }
return $out;
}
@@ -203,10 +206,12 @@ sub contact_page {
} else {
$intro .= $q->p(_('You are reporting the following problem report for being abusive, containing personal information, or similar:'));
$item_title = ent($p->{title});
+ my $date_time = Page::prettify_epoch($q, $p->{confirmed});
$item_meta = $q->em(
- 'Reported ',
- ($p->{anonymous}) ? 'anonymously' : "by " . ent($p->{name}),
- ' at ' . Page::prettify_epoch($q, $p->{confirmed}));
+ $p->{anonymous}
+ ? sprintf(_('Reported anonymously at %s'), $date_time)
+ : sprintf(_('Reported by %s at %s'), ent($p->{name}), $date_time)
+ );
$item_body = ent($p->{detail});
}
}
diff --git a/web/css/_main.scss b/web/css/_main.scss
new file mode 100644
index 000000000..1dd678271
--- /dev/null
+++ b/web/css/_main.scss
@@ -0,0 +1,135 @@
+// Generics
+
+body {
+ font-family: "Gill Sans", "Gill Sans MT", Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ // color: #a9aeb0;
+}
+
+h1 {
+ margin: 0;
+ font-size: 175%;
+}
+h2 {
+ font-size: 140%;
+}
+
+select, input, textarea {
+ font-size: 99%;
+}
+
+#mysociety {
+
+ a.unsuitable-report {
+ font-size: small;
+ }
+
+ blockquote {
+ border-left: solid 4px $header_colour;
+ }
+
+ .a {
+ color: #000000;
+ background-color: $header_back_lighter;
+ }
+
+ #postcodeForm {
+ background-color: $header_back;
+ }
+
+ #front_stats div {
+ background-color: $header_back;
+ }
+
+}
+
+// Site layout
+
+#header {
+ font-size: 200%;
+ font-weight: bold;
+ border-bottom: solid 2px $header_colour;
+ margin: 0;
+ padding: 0.15em 0.5em;
+ background-color: $header_back;
+ color: $header_colour;
+
+ a:link, a:visited {
+ color: $header_colour;
+ background-color: $header_back;
+ text-decoration: none;
+ }
+ a:active, a:hover {
+ text-decoration: underline;
+ }
+}
+
+#my {
+ color: $header_darker;
+ background-color: $header_back;
+}
+
+#mysociety {
+ width: 100%; /* Must specify a width or IE goes crazy wrong! */
+ position: relative;
+ margin: 0 auto;
+ max-width: 60em;
+}
+
+/* Can't put the margin in #mysociety because of above IE craziness */
+#wrapper {
+ margin: 2em;
+}
+
+#navigation {
+ position: absolute;
+ top: 1em;
+ right: 1em;
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+
+ li {
+ display: inline;
+ padding: 0;
+ margin: 0;
+ }
+
+ a {
+ display: -moz-inline-box;
+ display: inline-block;
+ padding: 0.4em 1em;
+ }
+ a:link, a:visited {
+ color: $header_colour;
+ }
+ a:hover, a:active {
+ background-color: $header_colour;
+ color: $header_back;
+ }
+}
+
+#nav_new a {
+ background-image: url("/i/new.png");
+ background-repeat: no-repeat;
+ background-position: 100% 0;
+}
+
+#logo {
+ border: none;
+ position: absolute;
+ top: 3.3em;
+ right: 10px;
+}
+
+#footer {
+ clear: both;
+ text-align: right;
+ font-size: 83%;
+ border-top: solid 1px $header_colour;
+ display: table;
+ margin: 2em 0 1em auto;
+ padding: 2px 4px;
+}
+
diff --git a/web/css/cobrands/emptyhomes/emptyhomes.css b/web/css/cobrands/emptyhomes/emptyhomes.css
index 2dcdce523..15afee568 100644
--- a/web/css/cobrands/emptyhomes/emptyhomes.css
+++ b/web/css/cobrands/emptyhomes/emptyhomes.css
@@ -93,14 +93,14 @@ blockquote {
margin-top: 0.5em;
}
-#content {
+#mysociety {
width: 100%; /* Must specify a width or IE goes crazy wrong! */
position: relative;
margin: 0 auto;
max-width: 60em;
}
-/* Can't put the margin in #content because of above IE craziness */
+/* Can't put the margin in #mysociety because of above IE craziness */
#wrapper {
clear: both;
margin: 0 2em 2em;
diff --git a/web/css/core.css b/web/css/core.css
index 5c8dad666..fb3ea393f 100644
--- a/web/css/core.css
+++ b/web/css/core.css
@@ -1,484 +1,380 @@
-/* Generics */
-
-blockquote {
- border-left: solid 4px #666666;
- padding-left: 0.5em;
-}
-blockquote h2, blockquote p {
- margin: 0;
-}
-
-form {
- margin: 0;
-}
-
-label {
- float: left;
- text-align: right;
- padding-right: 0.5em;
- width: 5em;
-}
-
-fieldset, #fieldset {
- border: none;
- padding: 0.5em;
-}
-
-legend {
- display: none;
-}
-
-dt {
- font-weight: bold;
- margin-top: 0.5em;
-}
-
-.v { display: none; }
-
-.gone {
- color: #666666;
- background-color: #cccccc;
-}
-
-p.error {
- text-align: center;
- color: #cc0000;
- font-size: larger;
-}
-
-ul {
- padding: 0 0 0 1.5em;
- margin: 0;
-}
-
-ul.error {
- color: #cc0000;
- background-color: #ffeeee;
- padding-right: 4px;
- text-align: left;
- font-size: larger;
-}
-
-div.form-error {
- color: #cc0000;
- margin: 5px 1em 5px 1em;
- padding: 2px 5px 2px 5px;
- float: left;
- background-color: #ffeeee;
- text-align: left;
-}
-
-div.form-field {
- clear: both;
-}
-
-/* Site-wide layout */
-
-#advert_thin {
- width: 50%;
- margin: 1em auto;
- border-top: dotted 1px #999999;
-}
-#advert_hfymp {
- border-top: dotted 1px #999999;
- text-align: center;
-}
-
-/* Front page */
-
-p#expl {
- text-align: center;
- font-size: 150%;
- margin: 0 2em;
-}
-
-#postcodeForm {
- display: table;
- _width: 33em;
- text-align: center;
- font-size: 150%;
- margin: 1em auto;
- padding: 1em;
- -moz-border-radius: 1em;
- -webkit-border-radius: 1em;
- border-radius: 1em;
+#mysociety blockquote {
+ border-left: solid 4px #666666;
+ padding-left: 0.5em;
+}
+#mysociety blockquote h2, #mysociety blockquote p {
+ margin: 0;
+}
+#mysociety dt {
+ font-weight: bold;
+ margin-top: 0.5em;
+}
+#mysociety .v {
+ display: none;
+}
+#mysociety .gone {
+ color: #666666;
+ background-color: #cccccc;
+}
+#mysociety p.error {
+ text-align: center;
+ color: #cc0000;
+ font-size: larger;
+}
+#mysociety ul {
+ padding: 0 0 0 1.5em;
+ margin: 0;
+}
+#mysociety ul.error {
+ color: #cc0000;
+ background-color: #ffeeee;
+ padding-right: 4px;
+ text-align: left;
+ font-size: larger;
+}
+#mysociety div.form-error {
+ color: #cc0000;
+ margin: 5px 1em 5px 1em;
+ padding: 2px 5px 2px 5px;
+ float: left;
+ background-color: #ffeeee;
+ text-align: left;
+}
+#mysociety div.form-field {
+ clear: both;
+}
+#mysociety #advert_thin {
+ width: 50%;
+ margin: 1em auto;
+ border-top: dotted 1px #999999;
+}
+#mysociety #advert_hfymp {
+ border-top: dotted 1px #999999;
+ text-align: center;
+}
+#mysociety p#expl {
+ text-align: center;
+ font-size: 150%;
+ margin: 0 2em;
+}
+#mysociety #postcodeForm {
+ display: table;
+ _width: 33em;
+ text-align: center;
+ font-size: 150%;
+ margin: 1em auto;
+ padding: 1em;
+ -moz-border-radius: 1em;
+ -webkit-border-radius: 1em;
+ border-radius: 1em;
+}
+#mysociety #postcodeForm label {
+ float: none;
+ padding-right: 0;
+}
+#mysociety #postcodeForm #submit {
+ font-size: 83%;
+}
+#mysociety #front_intro {
+ float: left;
+ width: 48%;
+}
+#mysociety #front_intro p {
+ clear: both;
+ margin-top: 0;
+}
+#mysociety #front_stats div {
+ text-align: center;
+ width: 5.5em;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+ float: left;
+ margin: 0 1em 1em;
+}
+#mysociety #front_stats div big {
+ font-size: 150%;
+ display: block;
+}
+#mysociety #front_recent {
+ float: right;
+ width: 48%;
+ margin-bottom: 1em;
+}
+#mysociety #front_recent img, #mysociety #alert_recent img {
+ margin-right: 0.25em;
+ margin-bottom: 0.25em;
+}
+#mysociety #front_recent > h2:first-child, #mysociety #front_intro > h2:first-child {
+ margin-top: 0;
+}
+#mysociety form {
+ margin: 0;
+}
+#mysociety label {
+ float: left;
+ text-align: right;
+ padding-right: 0.5em;
+ width: 5em;
+}
+#mysociety fieldset, #mysociety #fieldset {
+ border: none;
+ padding: 0.5em;
+}
+#mysociety fieldset div, #mysociety #fieldset div {
+ margin-top: 2px;
+ clear: left;
+}
+#mysociety legend {
+ display: none;
+}
+#mysociety #fieldset div.checkbox, #mysociety #problem_submit {
+ padding-left: 5.5em;
+}
+#mysociety #fieldset div.checkbox label, #mysociety label.n {
+ float: none;
+ text-align: left;
+ padding-right: 0;
+ width: auto;
+ cursor: pointer;
+ cursor: hand;
+}
+#mysociety #questionnaire label, #mysociety #alerts label {
+ float: none;
+}
+#mysociety .confirmed {
+ background-color: #ccffcc;
+ border: solid 2px #009900;
+ padding: 5px;
+ text-align: center;
+}
+#mysociety #watermark {
+ background: url("/i/mojwatermark6.png");
+ height: 113px;
+ width: 231px;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+}
+#mysociety #map_box {
+ float: right;
+ width: 502px;
+ position: relative;
+ padding-left: 20px;
+ background-color: #ffffff;
+}
+#mysociety p#copyright {
+ float: right;
+ margin: 0 0 1em 0;
+ font-size: 78%;
+}
+#mysociety #map {
+ border: solid 1px #000000;
+ width: 500px;
+ height: 500px;
+ overflow: hidden;
+ position: relative;
+ background-color: #f1f1f1;
+}
+#mysociety #drag {
+ position: absolute;
+ width: 500px;
+ height: 500px;
+ right: 0;
+ top: 0;
+}
+#mysociety #drag input, #mysociety #drag img {
+ position: absolute;
+ border: none;
+}
+#mysociety #drag input {
+ cursor: crosshair;
+ background-color: #cccccc;
+}
+#mysociety #drag img {
+ cursor: move;
+}
+#mysociety #drag img.pin {
+ z-index: 100;
+ background-color: inherit;
+}
+#mysociety #drag a img.pin {
+ cursor: pointer;
+ cursor: hand;
+}
+#mysociety form#mapForm #map {
+ cursor: pointer;
+}
+#mysociety form#mapForm .olTileImage {
+ cursor: crosshair;
+}
+#mysociety #compass {
+ background-color: #ffffff;
+ border: solid 1px #000000;
+ border-width: 0 1px 1px 0;
+ color: #000000;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+}
+#mysociety #compass img {
+ border: 0;
+}
+#mysociety #text_map {
+ margin-top: 0.5em;
+ margin-bottom: 1em;
+ font-size: 110%;
+}
+#mysociety #text_no_map {
+ margin-top: 0;
+}
+#mysociety #sub_map_links {
+ float: right;
+ clear: right;
+ margin-top: 0;
+}
+#mysociety #fixed {
+ margin: 0 530px 1em 0;
+ padding: 5px;
+ text-align: center;
+ position: relative;
+ background-color: #ccffcc;
+ border: solid 2px #009900;
+}
+#mysociety #unknown {
+ margin: 0 530px 1em 0;
+ padding: 5px;
+ text-align: center;
+ position: relative;
+ background-color: #ffcccc;
+ border: solid 2px #990000;
+}
+#mysociety #updates div {
+ padding: 0 0 0.5em;
+ margin: 0 0 0.25em;
+ border-bottom: dotted 1px #5e552b;
+}
+#mysociety #updates div .problem-update, #mysociety #updates div .update-text {
+ padding: 0;
+ margin: 0;
+ border-bottom: 0;
+}
+#mysociety #updates p {
+ margin: 0;
+}
+#mysociety #nearby_lists h2 {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+}
+#mysociety #alert_links {
+ float: right;
+}
+#mysociety #alert_links_area {
+ background-color: #ffeecc;
+ border: solid 1px #ff9900;
+ border-width: 1px 0;
+ padding: 3px 10px;
+ margin: 0;
+}
+#mysociety #rss_alert {
+ text-decoration: none;
+}
+#mysociety #rss_alert span {
+ text-decoration: underline;
+}
+#mysociety #email_alert_box {
+ display: none;
+ position: absolute;
+ padding: 3px;
+ font-size: 83%;
+ border: solid 1px #7399C3;
+ background-color: #eeeeff;
+ color: #000000;
+}
+#mysociety #email_alert_box p {
+ margin: 0;
+}
+#mysociety .council_sent_info {
+ font-size: smaller;
+}
+#mysociety #rss_items {
+ width: 62%;
+ float: left;
+}
+#mysociety #rss_rhs {
+ border-left: 1px dashed #999;
+ width: 36%;
+ float: right;
+ padding: 0 0 0 0.5em;
+ margin: 0 0 1em 0.5em;
+}
+#mysociety #rss_box {
+ padding: 10px;
+ border: 1px solid #999999;
+}
+#mysociety #rss_feed {
+ list-style-type: none;
+ margin-bottom: 2em;
+}
+#mysociety #rss_feed li {
+ margin-bottom: 1em;
+}
+#mysociety #alert_or {
+ font-style: italic;
+ font-size: 125%;
+ margin: 0;
+}
+#mysociety #rss_list {
+ float: left;
+ width: 47%;
+}
+#mysociety #rss_list ul {
+ list-style-type: none;
+}
+#mysociety #rss_buttons {
+ float: right;
+ width: 35%;
+ text-align: center;
+ margin-bottom: 2em;
+}
+#mysociety #rss_local {
+ margin-left: 1.5em;
+ margin-bottom: 0;
+}
+#mysociety #rss_local_alt {
+ margin: 0 0 2em 4em;
+}
+#mysociety #alert_photos {
+ text-align: center;
+ float: right;
+ width: 150px;
+ margin-left: 0.5em;
+}
+#mysociety #alert_photos h2 {
+ font-size: 100%;
}
-
-#postcodeForm label {
- float: none;
- padding-right: 0;
-}
-
-#postcodeForm #submit {
- font-size: 83%;
-}
-
-#front_intro {
- float: left;
- width: 48%;
-}
-
-#front_intro p {
- clear: both;
- margin-top: 0;
-}
-
-#front_stats div {
- text-align: center;
- width: 5.5em;
- -moz-border-radius: 0.5em;
- -webkit-border-radius: 0.5em;
- border-radius: 0.5em;
- float: left;
- margin: 0 1em 1em;
-}
-
-#front_stats div big {
- font-size: 150%;
- display: block;
-}
-
-#front_recent {
- float: right;
- width: 48%;
- margin-bottom: 1em;
-}
-#front_recent img, #alert_recent img {
- margin-right: 0.25em;
- margin-bottom: 0.25em;
-}
-#front_recent > h2:first-child, #front_intro > h2:first-child {
- margin-top: 0;
-}
-
-/* Forms */
-
-fieldset div, #fieldset div {
- margin-top: 2px;
- clear: left;
-}
-#fieldset div.checkbox, #problem_submit {
- padding-left: 5.5em;
-}
-#fieldset div.checkbox label, label.n {
- float: none;
- text-align: left;
- padding-right: 0;
- width: auto;
- cursor: pointer;
- cursor: hand;
+#mysociety #alert_photos img {
+ margin-bottom: 0.25em;
}
-
-#questionnaire label, #alerts label {
- float: none;
-}
-
-.confirmed {
- background-color: #ccffcc;
- border: solid 2px #009900;
- padding: 5px;
- text-align: center;
+#mysociety #col_problems, #mysociety #col_fixed {
+ float: left;
+ width: 48%;
+ margin-right: 1em;
}
-
-/* Map */
-
-#watermark {
- background: url("/i/mojwatermark6.png");
- height: 113px;
- width: 231px;
- position: absolute;
- bottom: 0;
- right: 0;
-}
-
-#map_box {
- float: right;
- width: 502px; /* Two pixels more than width of #map */
- position: relative;
- padding-left: 20px;
- background-color: #ffffff;
-}
-
-p#copyright {
- float: right;
- margin: 0 0 1em 0;
- font-size: 78%;
-}
-
-#map {
- border: solid 1px #000000;
- width: 500px; /* Twice a tile width */
- height: 500px;
- overflow: hidden;
- position: relative;
- background-color: #f1f1f1;
+#mysociety .contact-details {
+ font-size: 80%;
+ margin-top: 2em;
}
-#drag {
- position: absolute;
- width: 500px;
- height: 500px;
- right: 0;
- top: 0;
-}
-
-#drag input {
- cursor: crosshair;
- background-color: #cccccc;
-}
-#drag img {
- cursor: move;
-}
-#drag input, #drag img {
- position: absolute;
- border: none;
-}
-#drag img.pin {
- z-index: 100;
- background-color: inherit;
-}
-#drag a img.pin {
- cursor: pointer;
- cursor: hand;
-}
-
-#compass {
- background-color: #ffffff;
- border: solid 1px #000000;
- border-width: 0 1px 1px 0;
- color: #000000;
- position: absolute;
- top: 0px;
- left: 0px;
-}
-
-#compass img {
- border: 0;
-}
-
-#text_map {
- margin-top: 0.5em;
- margin-bottom: 1em;
- font-size: 110%;
-}
-#text_no_map {
- margin-top: 0;
- /* background-color: #ffeecc;
- padding: 4px; */
-}
-
-#sub_map_links {
- float: right;
- clear: right;
- margin-top: 0;
-}
-
-/* Problem pages */
-
-#fixed, #unknown {
- margin: 0 530px 1em 0;
- padding: 5px;
- text-align: center;
- position: relative;
-}
-#fixed {
- background-color: #ccffcc;
- border: solid 2px #009900;
-}
-#unknown {
- background-color: #ffcccc;
- border: solid 2px #990000;
-}
-
-#updates div {
- padding: 0 0 0.5em;
- margin: 0 0 0.25em;
- border-bottom: dotted 1px #5e552b;
-}
-
-#updates div .problem-update,
-#updates div .update-text {
- padding: 0;
- margin: 0;
- border-bottom: 0;
-}
-#updates p {
- margin: 0;
-}
-
-#nearby_lists h2 {
- margin-top: 0.5em;
- margin-bottom: 0;
-}
-#alert_links {
- float: right;
-}
-#alert_links_area {
- background-color: #ffeecc;
- border: solid 1px #ff9900;
- border-width: 1px 0;
- padding: 3px 10px;
- /* padding: 0 3px; */
- margin: 0;
-}
-#rss_alert {
- text-decoration: none;
-}
-#rss_alert span {
- text-decoration: underline;
-}
-#email_alert {
-}
-#email_alert_box {
- display:none;
- position: absolute;
- padding: 3px;
- font-size:83%;
- border:solid 1px #7399C3;
- background-color: #eeeeff;
- color: #000000;
-}
-#email_alert_box p {
- margin: 0;
-}
-
-.council_sent_info {
- font-size: smaller;
-}
-
-/* RSS feed XSL */
-
-#rss_items {
- width:62%;
- float:left;
-}
-#rss_rhs {
- border-left:1px dashed #999;
- width:36%;
- float:right;
- padding: 0 0 0 0.5em;
- margin: 0 0 1em 0.5em;
-}
-#rss_box {
- padding:10px;
- border:1px solid #999999;
-}
-
-/* Alerts */
-#rss_feed {
- list-style-type: none;
- margin-bottom: 2em;
-}
-#rss_feed li {
- margin-bottom: 1em;
-}
-#alert_or {
- font-style: italic;
- font-size: 125%;
- margin: 0;
-}
-#rss_list {
- float: left;
- width: 47%;
-}
-#rss_list ul {
- list-style-type: none;
-}
-#rss_buttons {
- float: right;
- width: 35%;
- text-align: center;
- margin-bottom: 2em;
-}
-#rss_local {
- margin-left: 1.5em;
- margin-bottom: 0;
-}
-#rss_local_alt {
- margin: 0 0 2em 4em;
-}
-
-#alert_photos {
- text-align: center;
- float: right;
- width: 150px;
- margin-left: 0.5em;
-}
-#alert_photos h2 {
- font-size: 100%;
-}
-#alert_photos img {
- margin-bottom: 0.25em;
-}
-
-/* Report page */
-
-#col_problems, #col_fixed {
- float: left;
- width: 48%;
- margin-right: 1em;
-}
-
-/* Contact page */
-.contact-details {
- font-size: 80%;
- margin-top: 2em;
-}
-
-/* Printing */
@media print {
- #map_box { float: none; margin: 0 auto; }
- #content { max-width: none; }
- #side { margin-right: 0; }
-}
-
-/* File upload */
-.progressContainer {
- margin: 5px;
- padding: 4px;
- width: 357px;
- border: solid 1px #E8E8E8;
- background-color: #F7F7F7;
- overflow: hidden;
-}
-.red { border: solid 1px #B50000; background-color: #FFEBEB; }
-.green { border: solid 1px #DDF0DD; background-color: #EBFFEB; }
-.blue { border: solid 1px #CEE2F2; background-color: #F0F5FF; }
-
-.progressName {
- font-size: 8pt;
- font-weight: bold;
- color: #555555;
- width: 323px;
- height: 14px;
- text-align: left;
- white-space: nowrap;
- overflow: hidden;
-}
-.progressBarInProgress, .progressBarComplete, .progressBarError {
- font-size: 0px;
- width: 0%;
- height: 2px;
- background-color: blue;
- margin-top: 2px;
-}
-.progressBarComplete {
- width: 100%;
- background-color: green;
- visibility: hidden;
-}
-.progressBarError {
- width: 100%;
- background-color: red;
- visibility: hidden;
-}
-.progressBarStatus {
- margin-top: 2px;
- width: 337px;
- font-size: 7pt;
- font-family: Verdana;
- text-align: left;
- white-space: nowrap;
+ #mysociety #map_box {
+ float: none;
+ margin: 0 auto;
+ }
+ #mysociety #mysociety {
+ max-width: none;
+ }
+ #mysociety #side {
+ margin-right: 0;
+ }
}
-
-
diff --git a/web/css/core.scss b/web/css/core.scss
new file mode 100644
index 000000000..ed8667983
--- /dev/null
+++ b/web/css/core.scss
@@ -0,0 +1,507 @@
+$map_width: 500px;
+
+@mixin problem-banner {
+ margin: 0 $map_width + 30px 1em 0;
+ padding: 5px;
+ text-align: center;
+ position: relative;
+}
+
+// Generics
+
+#mysociety {
+
+ blockquote {
+ border-left: solid 4px #666666;
+ padding-left: 0.5em;
+ h2, p {
+ margin: 0;
+ }
+ }
+
+ dt {
+ font-weight: bold;
+ margin-top: 0.5em;
+ }
+
+ .v {
+ display: none;
+ }
+
+ .gone {
+ color: #666666;
+ background-color: #cccccc;
+ }
+
+ p.error {
+ text-align: center;
+ color: #cc0000;
+ font-size: larger;
+ }
+
+ ul {
+ padding: 0 0 0 1.5em;
+ margin: 0;
+ }
+
+ ul.error {
+ color: #cc0000;
+ background-color: #ffeeee;
+ padding-right: 4px;
+ text-align: left;
+ font-size: larger;
+ }
+
+ div.form-error {
+ color: #cc0000;
+ margin: 5px 1em 5px 1em;
+ padding: 2px 5px 2px 5px;
+ float: left;
+ background-color: #ffeeee;
+ text-align: left;
+ }
+
+ div.form-field {
+ clear: both;
+ }
+
+ // Site-wide layout
+
+ #advert_thin {
+ width: 50%;
+ margin: 1em auto;
+ border-top: dotted 1px #999999;
+ }
+ #advert_hfymp {
+ border-top: dotted 1px #999999;
+ text-align: center;
+ }
+
+ // Front page
+
+ p#expl {
+ text-align: center;
+ font-size: 150%;
+ margin: 0 2em;
+ }
+
+ #postcodeForm {
+ display: table;
+ _width: 33em;
+ text-align: center;
+ font-size: 150%;
+ margin: 1em auto;
+ padding: 1em;
+ -moz-border-radius: 1em;
+ -webkit-border-radius: 1em;
+ border-radius: 1em;
+
+ label {
+ float: none;
+ padding-right: 0;
+ }
+
+ #submit {
+ font-size: 83%;
+ }
+ }
+
+ #front_intro {
+ float: left;
+ width: 48%;
+
+ p {
+ clear: both;
+ margin-top: 0;
+ }
+ }
+
+ #front_stats div {
+ text-align: center;
+ width: 5.5em;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+ float: left;
+ margin: 0 1em 1em;
+
+ big {
+ font-size: 150%;
+ display: block;
+ }
+ }
+
+ #front_recent {
+ float: right;
+ width: 48%;
+ margin-bottom: 1em;
+ }
+ #front_recent img, #alert_recent img {
+ margin-right: 0.25em;
+ margin-bottom: 0.25em;
+ }
+ #front_recent > h2:first-child, #front_intro > h2:first-child {
+ margin-top: 0;
+ }
+
+ // Forms
+
+ form {
+ margin: 0;
+ }
+
+ label {
+ float: left;
+ text-align: right;
+ padding-right: 0.5em;
+ width: 5em;
+ }
+
+ fieldset, #fieldset {
+ border: none;
+ padding: 0.5em;
+ div {
+ margin-top: 2px;
+ clear: left;
+ }
+ }
+
+ legend {
+ display: none;
+ }
+
+ #fieldset div.checkbox, #problem_submit {
+ padding-left: 5.5em;
+ }
+ #fieldset div.checkbox label, label.n {
+ float: none;
+ text-align: left;
+ padding-right: 0;
+ width: auto;
+ cursor: pointer;
+ cursor: hand;
+ }
+
+ #questionnaire label, #alerts label {
+ float: none;
+ }
+
+ .confirmed {
+ background-color: #ccffcc;
+ border: solid 2px #009900;
+ padding: 5px;
+ text-align: center;
+ }
+
+ // Map
+
+ #watermark {
+ background: url("/i/mojwatermark6.png");
+ height: 113px;
+ width: 231px;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ }
+
+ #map_box {
+ float: right;
+ width: $map_width + 2px;
+ position: relative;
+ padding-left: 20px;
+ background-color: #ffffff;
+ }
+
+ p#copyright {
+ float: right;
+ margin: 0 0 1em 0;
+ font-size: 78%;
+ }
+
+ #map {
+ border: solid 1px #000000;
+ width: $map_width; // Twice a tile width
+ height: $map_width;
+ overflow: hidden;
+ position: relative;
+ background-color: #f1f1f1;
+ }
+
+ #drag {
+ position: absolute;
+ width: $map_width;
+ height: $map_width;
+ right: 0;
+ top: 0;
+
+ input, img {
+ position: absolute;
+ border: none;
+ }
+ input {
+ cursor: crosshair;
+ background-color: #cccccc;
+ }
+ img {
+ cursor: move;
+ }
+ img.pin {
+ z-index: 100;
+ background-color: inherit;
+ }
+ a img.pin {
+ cursor: pointer;
+ cursor: hand;
+ }
+ }
+
+ form#mapForm #map {
+ cursor: pointer;
+ }
+
+ form#mapForm .olTileImage {
+ cursor: crosshair;
+ }
+
+ #compass {
+ background-color: #ffffff;
+ border: solid 1px #000000;
+ border-width: 0 1px 1px 0;
+ color: #000000;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ img {
+ border: 0;
+ }
+ }
+
+ #text_map {
+ margin-top: 0.5em;
+ margin-bottom: 1em;
+ font-size: 110%;
+ }
+ #text_no_map {
+ margin-top: 0;
+ // background-color: #ffeecc;
+ // padding: 4px;
+ }
+
+ #sub_map_links {
+ float: right;
+ clear: right;
+ margin-top: 0;
+ }
+
+ // Problem pages
+
+ #fixed {
+ @include problem-banner;
+ background-color: #ccffcc;
+ border: solid 2px #009900;
+ }
+
+ #unknown {
+ @include problem-banner;
+ background-color: #ffcccc;
+ border: solid 2px #990000;
+ }
+
+ #updates {
+ div {
+ padding: 0 0 0.5em;
+ margin: 0 0 0.25em;
+ border-bottom: dotted 1px #5e552b;
+
+ .problem-update, .update-text {
+ padding: 0;
+ margin: 0;
+ border-bottom: 0;
+ }
+ }
+
+ p {
+ margin: 0;
+ }
+ }
+
+ #nearby_lists h2 {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ }
+ #alert_links {
+ float: right;
+ }
+ #alert_links_area {
+ background-color: #ffeecc;
+ border: solid 1px #ff9900;
+ border-width: 1px 0;
+ padding: 3px 10px;
+ // padding: 0 3px;
+ margin: 0;
+ }
+ #rss_alert {
+ text-decoration: none;
+ span {
+ text-decoration: underline;
+ }
+ }
+ #email_alert {
+ }
+ #email_alert_box {
+ display:none;
+ position: absolute;
+ padding: 3px;
+ font-size:83%;
+ border:solid 1px #7399C3;
+ background-color: #eeeeff;
+ color: #000000;
+ }
+ #email_alert_box p {
+ margin: 0;
+ }
+
+ .council_sent_info {
+ font-size: smaller;
+ }
+
+ // RSS feed XSL
+
+ #rss_items {
+ width:62%;
+ float:left;
+ }
+ #rss_rhs {
+ border-left:1px dashed #999;
+ width:36%;
+ float:right;
+ padding: 0 0 0 0.5em;
+ margin: 0 0 1em 0.5em;
+ }
+ #rss_box {
+ padding:10px;
+ border:1px solid #999999;
+ }
+
+ // Alerts
+ #rss_feed {
+ list-style-type: none;
+ margin-bottom: 2em;
+ }
+ #rss_feed li {
+ margin-bottom: 1em;
+ }
+ #alert_or {
+ font-style: italic;
+ font-size: 125%;
+ margin: 0;
+ }
+ #rss_list {
+ float: left;
+ width: 47%;
+ }
+ #rss_list ul {
+ list-style-type: none;
+ }
+ #rss_buttons {
+ float: right;
+ width: 35%;
+ text-align: center;
+ margin-bottom: 2em;
+ }
+ #rss_local {
+ margin-left: 1.5em;
+ margin-bottom: 0;
+ }
+ #rss_local_alt {
+ margin: 0 0 2em 4em;
+ }
+
+ #alert_photos {
+ text-align: center;
+ float: right;
+ width: 150px;
+ margin-left: 0.5em;
+ }
+ #alert_photos h2 {
+ font-size: 100%;
+ }
+ #alert_photos img {
+ margin-bottom: 0.25em;
+ }
+
+ // Report page
+
+ #col_problems, #col_fixed {
+ float: left;
+ width: 48%;
+ margin-right: 1em;
+ }
+
+ // Contact page
+ .contact-details {
+ font-size: 80%;
+ margin-top: 2em;
+ }
+
+ // File upload
+ // .progressContainer {
+ // margin: 5px;
+ // padding: 4px;
+ // width: 357px;
+ // border: solid 1px #E8E8E8;
+ // background-color: #F7F7F7;
+ // overflow: hidden;
+ // }
+ // .red { border: solid 1px #B50000; background-color: #FFEBEB; }
+ // .green { border: solid 1px #DDF0DD; background-color: #EBFFEB; }
+ // .blue { border: solid 1px #CEE2F2; background-color: #F0F5FF; }
+
+ // .progressName {
+ // font-size: 8pt;
+ // font-weight: bold;
+ // color: #555555;
+ // width: 323px;
+ // height: 14px;
+ // text-align: left;
+ // white-space: nowrap;
+ // overflow: hidden;
+ // }
+ // .progressBarInProgress, .progressBarComplete, .progressBarError {
+ // font-size: 0px;
+ // width: 0%;
+ // height: 2px;
+ // background-color: blue;
+ // margin-top: 2px;
+ // }
+ // .progressBarComplete {
+ // width: 100%;
+ // background-color: green;
+ // visibility: hidden;
+ // }
+ // .progressBarError {
+ // width: 100%;
+ // background-color: red;
+ // visibility: hidden;
+ // }
+ // .progressBarStatus {
+ // margin-top: 2px;
+ // width: 337px;
+ // font-size: 7pt;
+ // font-family: Verdana;
+ // text-align: left;
+ // white-space: nowrap;
+ // }
+
+}
+
+// Printing, SCSS doesn't handle @media nesting
+
+@media print {
+ #mysociety {
+ #map_box { float: none; margin: 0 auto; }
+ #mysociety { max-width: none; }
+ #side { margin-right: 0; }
+ }
+}
+
diff --git a/web/css/ie6-378.css b/web/css/ie6-378.css
index e22f519ff..83efdb634 100644
--- a/web/css/ie6-378.css
+++ b/web/css/ie6-378.css
@@ -1,4 +1,4 @@
-#watermark {
+#mysociety #watermark {
background: none;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/i/mojwatermark-378.png',sizingMethod='scale');
}
diff --git a/web/css/ie6.css b/web/css/ie6.css
index cccb99f12..3bb91aa31 100644
--- a/web/css/ie6.css
+++ b/web/css/ie6.css
@@ -1,4 +1,4 @@
-#watermark {
+#mysociety #watermark {
background: none;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/i/mojwatermark6.png',sizingMethod='scale');
}
diff --git a/web/css/main.css b/web/css/main.css
index f1d416773..a7bb81d31 100644
--- a/web/css/main.css
+++ b/web/css/main.css
@@ -1,146 +1,130 @@
-/* Generics */
+a:link {
+ color: #0000ff;
+}
+a:visited {
+ color: #000099;
+}
+a:hover, a:active {
+ color: #ff0000;
+}
body {
- font-family: "Gill Sans", "Gill Sans MT", Helvetica, Arial, sans-serif;
- margin: 0;
- padding: 0;
- /* color: #a9aeb0; */
+ font-family: "Gill Sans", "Gill Sans MT", Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 0;
}
h1 {
- margin: 0;
- font-size: 175%;
+ margin: 0;
+ font-size: 175%;
}
+
h2 {
- font-size: 140%;
+ font-size: 140%;
}
select, input, textarea {
- font-size: 99%;
+ font-size: 99%;
}
-a:link {
- color: #0000ff;
+#mysociety a.unsuitable-report {
+ font-size: small;
}
-a:visited {
- color: #000099;
+#mysociety blockquote {
+ border-left: solid 4px #5e552b;
}
-a:hover, a:active {
- color: #ff0000;
+#mysociety .a {
+ color: #000000;
+ background-color: #f3e5a5;
}
-
-a.unsuitable-report {
- font-size: small;
+#mysociety #postcodeForm {
+ background-color: #e3d595;
}
-
-blockquote {
- border-left: solid 4px #5e552b;
+#mysociety #front_stats div {
+ background-color: #e3d595;
}
-.a {
- color: #000000;
- background-color: #f3e5a5;
-}
-
-/* Site layout */
-
#header {
- font-size: 200%;
- font-weight: bold;
- border-bottom: solid 2px #5e552b;
- margin: 0;
- padding: 0.15em 0.5em;
- background-color: #e3d595;
- color: #5e552b;
+ font-size: 200%;
+ font-weight: bold;
+ border-bottom: solid 2px #5e552b;
+ margin: 0;
+ padding: 0.15em 0.5em;
+ background-color: #e3d595;
+ color: #5e552b;
}
-
-#my {
- color: #4e451b;
- background-color: #e3d595;
-}
-#beta {
- color: #6e653b;
- background-color: #e3d595;
- font-size: 50%;
- font-style: italic;
-}
-
#header a:link, #header a:visited {
- color: #5e552b;
- background-color: #e3d595;
- text-decoration: none;
+ color: #5e552b;
+ background-color: #e3d595;
+ text-decoration: none;
}
#header a:active, #header a:hover {
- text-decoration: underline;
+ text-decoration: underline;
+}
+
+#my {
+ color: #4e451b;
+ background-color: #e3d595;
}
-#content {
- width: 100%; /* Must specify a width or IE goes crazy wrong! */
- position: relative;
- margin: 0 auto;
- max-width: 60em;
+#mysociety {
+ width: 100%;
+ /* Must specify a width or IE goes crazy wrong! */
+ position: relative;
+ margin: 0 auto;
+ max-width: 60em;
}
-/* Can't put the margin in #content because of above IE craziness */
+/* Can't put the margin in #mysociety because of above IE craziness */
#wrapper {
- margin: 2em;
+ margin: 2em;
}
#navigation {
- position: absolute;
- top: 1em;
- right: 1em;
- padding: 0;
- margin: 0;
- list-style-type: none;
+ position: absolute;
+ top: 1em;
+ right: 1em;
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
}
#navigation li {
- display: inline;
- padding: 0;
- margin: 0;
+ display: inline;
+ padding: 0;
+ margin: 0;
}
-
#navigation a {
- display: -moz-inline-box;
- display: inline-block;
- padding: 0.4em 1em;
+ display: -moz-inline-box;
+ display: inline-block;
+ padding: 0.4em 1em;
}
#navigation a:link, #navigation a:visited {
- color: #5e552b;
+ color: #5e552b;
}
#navigation a:hover, #navigation a:active {
- background-color: #5e552b;
- color: #e3d595;
+ background-color: #5e552b;
+ color: #e3d595;
}
#nav_new a {
- background-image: url("/i/new.png");
- background-repeat: no-repeat;
- background-position: 100% 0;
+ background-image: url("/i/new.png");
+ background-repeat: no-repeat;
+ background-position: 100% 0;
}
#logo {
- border: none;
- position: absolute;
- top: 3.3em;
- right: 10px;
+ border: none;
+ position: absolute;
+ top: 3.3em;
+ right: 10px;
}
#footer {
- clear: both;
- text-align: right;
- font-size: 83%;
- border-top: solid 1px #5e552b;
- display: table;
- margin: 2em 0 1em auto;
- padding: 2px 4px;
-}
-
-#postcodeForm {
- background-color: #e3d595;
+ clear: both;
+ text-align: right;
+ font-size: 83%;
+ border-top: solid 1px #5e552b;
+ display: table;
+ margin: 2em 0 1em auto;
+ padding: 2px 4px;
}
-
-#front_stats div {
- background-color: #e3d595;
-}
-
diff --git a/web/css/main.scss b/web/css/main.scss
new file mode 100644
index 000000000..bcebc2bd0
--- /dev/null
+++ b/web/css/main.scss
@@ -0,0 +1,14 @@
+// Generics
+
+$header_back: #e3d595;
+$header_back_lighter: #f3e5a5;
+$header_colour: #5e552b;
+$header_darker: #4e451b;
+
+a {
+ &:link { color: #0000ff; }
+ &:visited { color: #000099; }
+ &:hover, &:active { color: #ff0000; }
+}
+
+@import "_main";
diff --git a/web/down.default.html b/web/down.default.html
index 4e432473d..35d2cf237 100644
--- a/web/down.default.html
+++ b/web/down.default.html
@@ -12,7 +12,7 @@
<body>
<h1 id="header">Fix<span id="my">My</span>Street</h1>
-<div id="wrapper"><div id="content">
+<div id="wrapper"><div id="mysociety">
<p id="expl"><strong>FixMyStreet is currently down for maintenance.</strong>
<br><small>Please come back later.</small></p>
diff --git a/web/faq.cgi b/web/faq.cgi
index 2046f6955..4d9c7413a 100755
--- a/web/faq.cgi
+++ b/web/faq.cgi
@@ -16,16 +16,8 @@ my $lastmodified = (stat $0)[9];
sub main {
my $q = shift;
print Page::header($q, title=>_('Frequently Asked Questions'));
- if ($q->{site} eq 'emptyhomes') {
- my $lang = $mySociety::Locale::lang;
- if ($lang eq 'cy') {
- print File::Slurp::read_file("$FindBin::Bin/../templates/website/faq-eha.cy.html");
- } else {
- print File::Slurp::read_file("$FindBin::Bin/../templates/website/faq-eha.html");
- }
- } else {
- print File::Slurp::read_file("$FindBin::Bin/../templates/website/faq.html");
- }
+ my $lang = $mySociety::Locale::lang;
+ print Page::template_include("faq-$lang", $q, Page::template_root($q));
print Page::footer($q);
}
Page::do_fastcgi(\&main, $lastmodified);
diff --git a/web/import.cgi b/web/import.cgi
index 2aede1697..371e70f7a 100755
--- a/web/import.cgi
+++ b/web/import.cgi
@@ -13,16 +13,14 @@ use Error qw(:try);
use Standard;
use Utils;
use mySociety::AuthToken;
+use mySociety::Config;
use mySociety::EmailUtil;
-use mySociety::EvEl;
sub main {
my $q = shift;
my @vars = qw(service subject detail name email phone easting northing lat lon id phone_id);
my %input = map { $_ => $q->param($_) || '' } @vars;
- $input{easting} ||= 0;
- $input{northing} ||= 0;
my @errors;
unless ($ENV{REQUEST_METHOD} eq 'POST') {
@@ -32,6 +30,18 @@ sub main {
return;
}
+ # If we were given easting, northing convert to lat lon now
+ my $latitude = $input{lat} ||= 0;
+ my $longitude = $input{lon} ||= 0;
+ if (
+ !( $latitude || $longitude ) # have not been given lat or lon
+ && ( $input{easting} && $input{northing} ) # but do have e and n
+ )
+ {
+ ( $latitude, $longitude ) =
+ Utils::convert_en_to_latlon( $input{easting}, $input{northing});
+ }
+
my $fh = $q->upload('photo'); # MUST come before $q->header, don't know why!
print $q->header(-charset => 'utf-8', -content_type => 'text/plain');
@@ -50,14 +60,15 @@ sub main {
push @errors, 'Please enter a valid email';
}
- if ($input{lat}) {
+ if ( $latitude && mySociety::Config::get('COUNTRY') eq 'GB' ) {
try {
- ($input{easting}, $input{northing}) = mySociety::GeoUtil::wgs84_to_national_grid($input{lat}, $input{lon}, 'G');
- } catch Error::Simple with {
+ Utils::convert_latlon_to_en( $latitude, $longitude );
+ } catch Error::Simple with {
my $e = shift;
push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
};
}
+
# TODO: Get location from photo if present in EXIF data?
my $photo;
@@ -70,7 +81,7 @@ sub main {
};
}
- unless ($photo || ($input{easting} && $input{northing})) {
+ unless ( $photo || ( $latitude || $longitude ) ) {
push @errors, 'Either a location or a photo must be provided.';
}
@@ -92,30 +103,23 @@ sub main {
# Store what we have so far in the database
my $id = dbh()->selectrow_array("select nextval('problem_id_seq')");
Utils::workaround_pg_bytea("insert into problem
- (id, postcode, easting, northing, title, detail, name, service,
+ (id, postcode, latitude, longitude, title, detail, name, service,
email, phone, photo, state, used_map, anonymous, category, areas)
values
(?, '', ?, ?, ?, ?, ?, ?, ?, ?, ?, 'partial', 't', 'f', '', '')", 10,
- $id, $input{easting}, $input{northing}, $input{subject},
+ $id, $latitude, $longitude, $input{subject},
$input{detail}, $input{name}, $input{service}, $input{email}, $input{phone}, $photo);
- # Send checking email
- my $template = File::Slurp::read_file("$FindBin::Bin/../templates/emails/partial");
my $token = mySociety::AuthToken::store('partial', $id);
my %h = (
name => $input{name} ? ' ' . $input{name} : '',
- url => mySociety::Config::get('BASE_URL') . '/L/' . $token,
+ url => Page::base_url_with_lang($q, undef, 1) . '/L/' . $token,
service => $input{service},
+ title => $input{title},
+ detail => $input{detail},
);
- my $sender = mySociety::Config::get('CONTACT_EMAIL');
- $sender =~ s/team/fms-DO-NOT-REPLY/;
- mySociety::EvEl::send({
- _template_ => $template,
- _parameters_ => \%h,
- To => $input{name} ? [ [ $input{email}, $input{name} ] ] : $input{email},
- From => [ $sender, 'FixMyStreet' ],
- }, $input{email});
+ Page::send_email($q, $input{email}, $input{name}, 'partial', %h);
dbh()->commit();
print 'SUCCESS';
diff --git a/web/index.cgi b/web/index.cgi
index e503f50ba..c86ac6ad1 100755
--- a/web/index.cgi
+++ b/web/index.cgi
@@ -9,26 +9,34 @@
use strict;
use Standard;
use Utils;
+use Encode;
use Error qw(:try);
use File::Slurp;
-use LWP::Simple;
-use RABX;
use CGI::Carp;
+use POSIX qw(strcoll);
use URI::Escape;
+# use Carp::Always;
+
use CrossSell;
use FixMyStreet::Geocode;
use mySociety::AuthToken;
use mySociety::Config;
use mySociety::DBHandle qw(select_all);
use mySociety::EmailUtil;
-use mySociety::GeoUtil;
use mySociety::Locale;
use mySociety::MaPit;
use mySociety::PostcodeUtil;
use mySociety::Random;
use mySociety::VotingArea;
use mySociety::Web qw(ent NewURL);
+use Utils;
+
+sub debug (@) {
+ return;
+ my ( $format, @args ) = @_;
+ warn sprintf $format, map { defined $_ ? $_ : 'undef' } @args;
+}
BEGIN {
if (!dbh()->selectrow_array('select secret from secret for update of secret')) {
@@ -47,13 +55,13 @@ sub main {
my $id = mySociety::AuthToken::retrieve('partial', $partial);
if ($id) {
my @row = dbh()->selectrow_array(
- "select easting, northing, name, email, title, (photo is not null) as has_photo, phone, detail
+ "select latitude, longitude, name, email, title, (photo is not null) as has_photo, phone, detail
from problem where id=? and state='partial'", {}, $id);
if (@row) {
$q->param('anonymous', 1);
$q->param('submit_map', 1);
- $q->param('easting', $row[0]);
- $q->param('northing', $row[1]);
+ $q->param('latitude', $row[0]);
+ $q->param('longitude', $row[1]);
$q->param('name', $row[2]);
$q->param('email', $row[3]);
$q->param('title', $row[4]);
@@ -72,19 +80,21 @@ sub main {
my %params;
if ($q->param('submit_problem')) {
$params{title} = _('Submitting your report');
- ($out) = submit_problem($q);
+ ($out, %params) = submit_problem($q);
} elsif ($q->param('submit_update')) {
$params{title} = _('Submitting your update');
- ($out) = submit_update($q);
+ ($out, %params) = submit_update($q);
} elsif ($q->param('submit_map')) {
($out, %params) = display_form($q, [], {});
$params{title} = _('Reporting a problem');
} elsif ($q->param('id')) {
($out, %params) = display_problem($q, [], {});
$params{title} .= ' - ' . _('Viewing a problem');
- } elsif ($q->param('pc') || ($q->param('x') && $q->param('y')) || ($q->param('e') && $q->param('n'))) {
+ } elsif ($q->param('pc') || ($q->param('x') && $q->param('y')) || ($q->param('lat') || $q->param('lon'))) {
($out, %params) = display_location($q);
$params{title} = _('Viewing a location');
+ } elsif ($q->param('e') && $q->param('n')) {
+ ($out, %params) = redirect_from_osgb_to_wgs84($q);
} else {
($out, %params) = front_page($q);
}
@@ -107,6 +117,8 @@ sub front_page {
my $cobrand_form_elements = Cobrand::form_elements($cobrand, 'postcodeForm', $q);
my $form_action = Cobrand::url($cobrand, '/', $q);
my $question = Cobrand::enter_postcode_text($cobrand, $q);
+ $question = _("Enter a nearby GB postcode, or street name and area")
+ unless $question;
my %params = ('context' => 'front-page');
$params{status_code} = $status_code if $status_code;
my %vars = (
@@ -114,7 +126,7 @@ sub front_page {
pc_h => $pc_h,
cobrand_form_elements => $cobrand_form_elements,
form_action => $form_action,
- question => $question,
+ question => "$question:",
);
my $cobrand_front_page = Page::template_include('front-page', $q, Page::template_root($q), %vars);
return ($cobrand_front_page, %params) if $cobrand_front_page;
@@ -152,7 +164,7 @@ EOF
}
my $activate = _("Go");
$out .= <<EOF;
-<label for="pc">$question</label>
+<label for="pc">$question:</label>
&nbsp;<input type="text" name="pc" value="$pc_h" id="pc" size="10" maxlength="200">
&nbsp;<input type="submit" value="$activate" id="submit">
$cobrand_form_elements
@@ -247,13 +259,13 @@ sub submit_update {
$h{url} = $base . '/C/' . mySociety::AuthToken::store('update', { id => $id, add_alert => $input{add_alert} } );
dbh()->commit();
- my $out = Page::send_email($q, $input{rznvy}, $input{name}, 'update', %h);
+ my $out = Page::send_confirmation_email($q, $input{rznvy}, $input{name}, 'update', %h);
return $out;
}
sub submit_problem {
my $q = shift;
- my @vars = qw(council title detail name email phone pc easting northing skipped anonymous category partial upload_fileid lat lon);
+ my @vars = qw(council title detail name email phone pc skipped anonymous category partial upload_fileid latitude longitude);
my %input = map { $_ => scalar $q->param($_) } @vars;
for (qw(title detail)) {
$input{$_} = lc $input{$_} if $input{$_} !~ /[a-z]/;
@@ -265,15 +277,18 @@ sub submit_problem {
my @errors;
my %field_errors;
- if ($input{lat}) {
+ my $cobrand = Page::get_cobrand($q);
+
+ # If in UK and we have a lat,lon coocdinate check it is in UK
+ if ( $input{latitude} && mySociety::Config::get('COUNTRY') eq 'GB' ) {
try {
- ($input{easting}, $input{northing}) = mySociety::GeoUtil::wgs84_to_national_grid($input{lat}, $input{lon}, 'G');
+ Utils::convert_latlon_to_en( $input{latitude}, $input{longitude} );
} catch Error::Simple with {
my $e = shift;
push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
};
}
-
+
my $fh = $q->upload('photo');
if ($fh) {
my $err = Page::check_photo($q, $fh);
@@ -294,7 +309,7 @@ sub submit_problem {
} elsif (!mySociety::EmailUtil::is_valid_email($input{email})) {
$field_errors{email} = _('Please enter a valid email');
}
- if ($input{category} && $input{category} eq '-- Pick a category --') {
+ if ($input{category} && $input{category} eq _('-- Pick a category --')) {
$field_errors{category} = _('Please choose a category');
$input{category} = '';
} elsif ($input{category} && $input{category} eq _('-- Pick a property type --')) {
@@ -305,11 +320,13 @@ sub submit_problem {
return display_form($q, \@errors, \%field_errors) if (@errors || scalar keys %field_errors); # Short circuit
my $areas;
- if ($input{easting} && $input{northing}) {
- $areas = mySociety::MaPit::call('point', "27700/$input{easting},$input{northing}");
+ if (defined $input{latitude} && defined $input{longitude}) {
+ my $mapit_query = "4326/$input{longitude},$input{latitude}";
+ $areas = mySociety::MaPit::call( 'point', $mapit_query );
if ($input{council} =~ /^[\d,]+(\|[\d,]+)?$/) {
my $no_details = $1 || '';
- my %va = map { $_ => 1 } @$mySociety::VotingArea::council_parent_types;
+ my @area_types = Cobrand::area_types($cobrand);
+ my %va = map { $_ => 1 } @area_types;
my %councils;
foreach (keys %$areas) {
$councils{$_} = 1 if $va{$areas->{$_}->{type}};
@@ -345,10 +362,10 @@ sub submit_problem {
$input{council} = join(',', @valid_councils) . $no_details;
}
$areas = ',' . join(',', sort keys %$areas) . ',';
- } elsif ($input{easting} || $input{northing}) {
+ } elsif (defined $input{latitude} || defined $input{longitude}) {
push(@errors, _('Somehow, you only have one co-ordinate. Please try again.'));
} else {
- push(@errors, _('You haven\'t specified any sort of co-ordinates. Please try again.'));
+ push(@errors, _("You haven't specified any sort of co-ordinates. Please try again."));
}
my $image;
@@ -373,15 +390,14 @@ sub submit_problem {
my $used_map = $input{skipped} ? 'f' : 't';
$input{category} = _('Other') unless $input{category};
my ($id, $out);
- my $cobrand = Page::get_cobrand($q);
my $cobrand_data = Cobrand::extra_problem_data($cobrand, $q);
if (my $token = $input{partial}) {
my $id = mySociety::AuthToken::retrieve('partial', $token);
if ($id) {
- dbh()->do("update problem set postcode=?, easting=?, northing=?, title=?, detail=?,
+ dbh()->do("update problem set postcode=?, latitude=?, longitude=?, title=?, detail=?,
name=?, email=?, phone=?, state='confirmed', council=?, used_map='t',
anonymous=?, category=?, areas=?, cobrand=?, cobrand_data=?, confirmed=ms_current_timestamp(),
- lastupdate=ms_current_timestamp() where id=?", {}, $input{pc}, $input{easting}, $input{northing},
+ lastupdate=ms_current_timestamp() where id=?", {}, $input{pc}, $input{latitude}, $input{longitude},
$input{title}, $input{detail}, $input{name}, $input{email},
$input{phone}, $input{council}, $input{anonymous} ? 'f' : 't',
$input{category}, $areas, $cobrand, $cobrand_data, $id);
@@ -400,11 +416,11 @@ Please <a href="/contact">let us know what went on</a> and we\'ll look into it.'
} else {
$id = dbh()->selectrow_array("select nextval('problem_id_seq');");
Utils::workaround_pg_bytea("insert into problem
- (id, postcode, easting, northing, title, detail, name,
+ (id, postcode, latitude, longitude, title, detail, name,
email, phone, photo, state, council, used_map, anonymous, category, areas, lang, cobrand, cobrand_data)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'unconfirmed', ?, ?, ?, ?, ?, ?, ?, ?)", 10,
- $id, $input{pc}, $input{easting}, $input{northing}, $input{title},
+ $id, $input{pc}, $input{latitude}, $input{longitude}, $input{title},
$input{detail}, $input{name}, $input{email}, $input{phone}, $image,
$input{council}, $used_map, $input{anonymous} ? 'f': 't', $input{category},
$areas, $mySociety::Locale::lang, $cobrand, $cobrand_data);
@@ -416,7 +432,7 @@ Please <a href="/contact">let us know what went on</a> and we\'ll look into it.'
$h{url} = $base . '/P/' . mySociety::AuthToken::store('problem', $id);
dbh()->commit();
- $out = Page::send_email($q, $input{email}, $input{name}, 'problem', %h);
+ $out = Page::send_confirmation_email($q, $input{email}, $input{name}, 'problem', %h);
}
return $out;
@@ -430,22 +446,29 @@ sub display_form {
push @errors, _('There were problems with your report. Please see below.') if (scalar keys %field_errors);
my ($pin_x, $pin_y, $pin_tile_x, $pin_tile_y) = (0,0,0,0);
- my @vars = qw(title detail name email phone pc easting northing x y skipped council anonymous partial upload_fileid lat lon);
- my %input = map { $_ => $q->param($_) || '' } @vars;
- my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
+ my @vars = qw(title detail name email phone pc latitude longitude x y skipped council anonymous partial upload_fileid);
- # Convert lat/lon to easting/northing if given
- if ($input{lat}) {
- try {
- ($input{easting}, $input{northing}) = mySociety::GeoUtil::wgs84_to_national_grid($input{lat}, $input{lon}, 'G');
- $input_h{easting} = $input{easting};
- $input_h{northing} = $input{northing};
- } catch Error::Simple with {
- my $e = shift;
- push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
- };
+ my %input = ();
+ my %input_h = ();
+
+ foreach my $key (@vars) {
+ my $val = $q->param($key);
+ $input{$key} = defined($val) ? $val : ''; # '0' is valid for longitude
+ $input_h{$key} = ent( $input{$key} );
}
+ # Convert lat/lon to easting/northing if given
+ # if ($input{lat}) {
+ # try {
+ # ($input{easting}, $input{northing}) = mySociety::GeoUtil::wgs84_to_national_grid($input{lat}, $input{lon}, 'G');
+ # $input_h{easting} = $input{easting};
+ # $input_h{northing} = $input{northing};
+ # } catch Error::Simple with {
+ # my $e = shift;
+ # push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
+ # };
+ # }
+
# Get tile co-ordinates if map clicked
($input{x}) = $input{x} =~ /^(\d+)/; $input{x} ||= 0;
($input{y}) = $input{y} =~ /^(\d+)/; $input{y} ||= 0;
@@ -458,28 +481,32 @@ sub display_form {
# We need either a map click, an E/N, to be skipping the map, or be filling in a partial form
return display_location($q, @errors)
unless ($pin_x && $pin_y)
- || ($input{easting} && $input{northing})
+ || ($input{latitude} && $input{longitude})
|| ($input{skipped} && $input{pc})
|| ($input{partial} && $input{pc});
# Work out some co-ordinates from whatever we've got
- my ($easting, $northing);
+ my ($latitude, $longitude);
if ($input{skipped}) {
# Map is being skipped
- if ($input{easting} && $input{northing}) {
- $easting = $input{easting};
- $northing = $input{northing};
+ if ( length $input{latitude} && length $input{longitude} ) {
+ $latitude = $input{latitude};
+ $longitude = $input{longitude};
} else {
- my ($e, $n, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
- $easting = $e; $northing = $n;
+ my ( $lat, $lon, $error ) =
+ FixMyStreet::Geocode::lookup( $input{pc}, $q );
+ $latitude = $lat;
+ $longitude = $lon;
}
} elsif ($pin_x && $pin_y) {
- # tilma map was clicked on
- ($easting, $northing) = FixMyStreet::Map::click_to_os($pin_tile_x, $pin_x, $pin_tile_y, $pin_y);
- } elsif ($input{partial} && $input{pc} && !$input{easting} && !$input{northing}) {
+
+ # Map was clicked on (tilma, or non-JS OpenLayers, for example)
+ ($latitude, $longitude) = FixMyStreet::Map::click_to_wgs84($q, $pin_tile_x, $pin_x, $pin_tile_y, $pin_y);
+
+ } elsif ( $input{partial} && $input{pc} && !length $input{latitude} && !length $input{longitude} ) {
my $error;
try {
- ($easting, $northing, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
+ ($latitude, $longitude, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
} catch Error::Simple with {
$error = shift;
};
@@ -487,28 +514,37 @@ sub display_form {
return front_page($q, $error) if $error;
} else {
# Normal form submission
- $easting = $input_h{easting};
- $northing = $input_h{northing};
+ $latitude = $input_h{latitude};
+ $longitude = $input_h{longitude};
}
+ # Shrink, as don't need accuracy plus we want them as English strings
+ ($latitude, $longitude) = map { Utils::truncate_coordinate($_) } ( $latitude, $longitude );
+
# Look up councils and do checks for the point we've got
- my $parent_types = $mySociety::VotingArea::council_parent_types;
- $parent_types = [qw(DIS LBO MTD UTA LGD COI)] # No CTY
- if $q->{site} eq 'emptyhomes';
+ my @area_types = Cobrand::area_types($cobrand);
# XXX: I think we want in_gb_locale around the next line, needs testing
- my $all_councils = mySociety::MaPit::call('point', "27700/$easting,$northing", type => $parent_types);
+ my $all_councils = mySociety::MaPit::call('point', "4326/$longitude,$latitude", type => \@area_types);
# Let cobrand do a check
my ($success, $error_msg) = Cobrand::council_check($cobrand, { all_councils => $all_councils }, $q, 'submit_problem');
- if (!$success){
+ if (!$success) {
return front_page($q, $error_msg);
}
- # Ipswich & St Edmundsbury are responsible for everything in their areas, no Suffolk
- delete $all_councils->{2241} if $all_councils->{2446} || $all_councils->{2443};
+ if (mySociety::Config::get('COUNTRY') eq 'GB') {
+ # Ipswich & St Edmundsbury are responsible for everything in their areas, not Suffolk
+ delete $all_councils->{2241} if $all_councils->{2446} || $all_councils->{2443};
+
+ # Norwich is responsible for everything in its areas, not Norfolk
+ delete $all_councils->{2233} if $all_councils->{2391};
+
+ } elsif (mySociety::Config::get('COUNTRY') eq 'NO') {
- # Norwich is responsible for everything in its areas, no Norfolk
- delete $all_councils->{2233} if $all_councils->{2391};
+ # Oslo is both a kommune and a fylke, we only want to show it once
+ delete $all_councils->{301} if $all_councils->{3};
+
+ }
return display_location($q, _('That spot does not appear to be covered by a council.
If you have tried to report an issue past the shoreline, for example,
@@ -520,7 +556,7 @@ please specify the closest point on land.')) unless %$all_councils;
my $categories = select_all("select area_id, category from contacts
where deleted='f' and area_id in (" . join(',', keys %$all_councils) . ')');
if ($q->{site} ne 'emptyhomes') {
- @$categories = sort { $a->{category} cmp $b->{category} } @$categories;
+ @$categories = sort { strcoll($a->{category}, $b->{category}) } @$categories;
foreach (@$categories) {
$council_ok{$_->{area_id}} = 1;
next if $_->{category} eq _('Other');
@@ -530,7 +566,7 @@ please specify the closest point on land.')) unless %$all_councils;
@categories = Page::scambs_categories();
}
if (@categories) {
- @categories = ('-- Pick a category --', @categories, _('Other'));
+ @categories = (_('-- Pick a category --'), @categories, _('Other'));
$category = _('Category:');
}
} else {
@@ -574,6 +610,8 @@ please specify the closest point on land.')) unless %$all_councils;
my $form_action = Cobrand::url($cobrand, '/', $q);
$vars{form_start} = <<EOF;
<form action="$form_action" method="post" name="mapSkippedForm"$enctype>
+<input type="hidden" name="latitude" value="$latitude">
+<input type="hidden" name="longitude" value="$longitude">
<input type="hidden" name="pc" value="$input_h{pc}">
<input type="hidden" name="skipped" value="1">
$cobrand_form_elements
@@ -587,9 +625,9 @@ EOF
$type = 1;
}
$vars{form_start} = FixMyStreet::Map::display_map($q,
- easting => $easting, northing => $northing,
+ latitude => $latitude, longitude => $longitude,
type => $type,
- pins => [ [ $easting, $northing, 'purple' ] ],
+ pins => [ [ $latitude, $longitude, 'purple' ] ],
);
my $partial_id;
if (my $token = $input{partial}) {
@@ -606,7 +644,7 @@ If this is not the correct location, simply click on the map again. '));
$vars{page_heading} = $q->h1(_('Reporting a problem'));
if ($details eq 'all') {
- my $council_list = join('</strong> or <strong>', map { $_->{name} } values %$all_councils);
+ my $council_list = join('</strong>' . _(' or ') . '<strong>', map { $_->{name} } values %$all_councils);
if ($q->{site} eq 'emptyhomes'){
$vars{text_help} = '<p>' . sprintf(_('All the information you provide here will be sent to <strong>%s</strong>.
On the site, we will show the subject and details of the problem, plus your
@@ -625,33 +663,37 @@ name if you give us permission.'), $council_list);
push @missing, $_ unless $councils{$_};
}
my $n = @missing;
- my $list = join(' or ', map { $all_councils->{$_}->{name} } @missing);
- $vars{text_help} = '<p>All the information you provide here will be sent to <strong>'
- . join('</strong> or <strong>', map { $all_councils->{$_}->{name} } @councils)
- . '</strong>. The subject and details of the problem will be public, plus your
-name if you give us permission.';
- $vars{text_help} .= ' We do <strong>not</strong> yet have details for the other council';
- $vars{text_help} .= ($n>1) ? 's that cover' : ' that covers';
- $vars{text_help} .= " this location. You can help us by finding a contact email address for local
-problems for $list and emailing it to us at <a href='mailto:$e'>$e</a>.";
+ my $list = join(_(' or '), map { $all_councils->{$_}->{name} } @missing);
+ $vars{text_help} = '<p>' . _('All the information you provide here will be sent to') . ' <strong>'
+ . join('</strong>' . _(' or ') . '<strong>', map { $all_councils->{$_}->{name} } @councils)
+ . '</strong>. ';
+ $vars{text_help} .= _('The subject and details of the problem will be public, plus your name if you give us permission.');
+ $vars{text_help} .= ' ' . mySociety::Locale::nget(
+ 'We do <strong>not</strong> yet have details for the other council that covers this location.',
+ 'We do <strong>not</strong> yet have details for the other councils that cover this location.',
+ $n
+ );
+ $vars{text_help} .= ' ' . sprintf(_("You can help us by finding a contact email address for local problems for %s and emailing it to us at <a href='mailto:%s'>%s</a>."), $list, $e, $e);
$vars{text_help} .= '<input type="hidden" name="council" value="' . join(',', @councils)
. '|' . join(',', @missing) . '">';
} else {
my $e = Cobrand::contact_email($cobrand);
- my $list = join(' or ', map { $_->{name} } values %$all_councils);
+ my $list = join(_(' or '), map { $_->{name} } values %$all_councils);
my $n = scalar keys %$all_councils;
if ($q->{site} ne 'emptyhomes') {
- $vars{text_help} = '<p>We do not yet have details for the council';
- $vars{text_help} .= ($n>1) ? 's that cover' : ' that covers';
- $vars{text_help} .= " this location. If you submit a problem here the subject and details
-of the problem will be public, but the problem will <strong>not</strong> be reported to the council.
-You can help us by finding a contact email address for local
-problems for $list and emailing it to us at <a href='mailto:$e'>$e</a>.";
+ $vars{text_help} = '<p>';
+ $vars{text_help} .= mySociety::Locale::nget(
+ 'We do not yet have details for the council that covers this location.',
+ 'We do not yet have details for the councils that cover this location.',
+ $n
+ );
+ $vars{text_help} .= _("If you submit a problem here the subject and details of the problem will be public, but the problem will <strong>not</strong> be reported to the council.");
+ $vars{text_help} .= sprintf(_("You can help us by finding a contact email address for local problems for %s and emailing it to us at <a href='mailto:%s'>%s</a>."), $list, $e, $e);
} else {
- $vars{text_help} = _("<p>We do not yet have details for the council that covers
-this location. If you submit a report here it will be left on the site, but
-not reported to the council &ndash; please still leave your report, so that
-we can show to the council the activity in their area.");
+ $vars{text_help} = '<p>'
+ . _('We do not yet have details for the council that covers this location.')
+ . ' '
+ . _("If you submit a report here it will be left on the site, but not reported to the council &ndash; please still leave your report, so that we can show to the council the activity in their area.");
}
$vars{text_help} .= '<input type="hidden" name="council" value="-1">';
}
@@ -682,10 +724,6 @@ photo of the problem if you have one), etc.'));
$vars{text_help} .= $q->p(_('Please fill in details of the problem below.'));
}
- $vars{text_help} .= '
-<input type="hidden" name="easting" value="' . $easting . '">
-<input type="hidden" name="northing" value="' . $northing . '">';
-
if (@errors) {
$vars{errors} = '<ul class="error"><li>' . join('</li><li>', @errors) . '</li></ul>';
}
@@ -731,27 +769,18 @@ EOF
}
if ($q->{site} ne 'emptyhomes') {
- $vars{text_notes} = <<EOF;
-<p>Please note:</p>
-<ul>
-<li>We will only use your personal
-information in accordance with our <a href="/faq#privacy">privacy policy.</a></li>
-<li>Please be polite, concise and to the point.</li>
-<li>Please do not be abusive &mdash; abusing your council devalues the service for all users.</li>
-<li>Writing your message entirely in block capitals makes it hard to read,
-as does a lack of punctuation.</li>
-<li>Remember that FixMyStreet is primarily for reporting physical
-problems that can be fixed. If your problem is not appropriate for
-submission via this site remember that you can contact your council
-directly using their own website.</li>
-<li>
-FixMyStreet and the Guardian are providing this service in
-partnership in <a href="/faq#privacy">certain cities</a>. In those cities, both have access to
-any information submitted, including names and email addresses, and will use it only to ensure the
-smooth running of the service, in accordance with their privacy policies.
-</li>
-</ul>
-EOF
+ $vars{text_notes} =
+ $q->p(_("Please note:")) .
+ "<ul>" .
+ $q->li(_("We will only use your personal information in accordance with our <a href=\"/faq#privacy\">privacy policy.</a>")) .
+ $q->li(_("Please be polite, concise and to the point.")) .
+ $q->li(_("Please do not be abusive &mdash; abusing your council devalues the service for all users.")) .
+ $q->li(_("Writing your message entirely in block capitals makes it hard to read, as does a lack of punctuation.")) .
+ $q->li(_("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."));
+ $vars{text_notes} .=
+ $q->li(_("FixMyStreet and the Guardian are providing this service in partnership in <a href=\"/faq#privacy\">certain cities</a>. In those cities, both have access to any information submitted, including names and email addresses, and will use it only to ensure the smooth running of the service, in accordance with their privacy policies."))
+ if mySociety::Config::get('COUNTRY') eq 'GB';
+ $vars{text_notes} .= "</ul>\n";
}
%vars = (%vars,
@@ -760,43 +789,93 @@ EOF
url_home => Cobrand::url($cobrand, '/', $q),
submit_button => _('Submit')
);
- return (Page::template_include('report-form', $q, Page::template_root($q), %vars), robots => 'noindex,nofollow');
+ return (Page::template_include('report-form', $q, Page::template_root($q), %vars),
+ robots => 'noindex,nofollow',
+ js => FixMyStreet::Map::header_js(),
+ );
+}
+
+# redirect from osgb
+sub redirect_from_osgb_to_wgs84 {
+ my ($q) = @_;
+
+ my $e = $q->param('e');
+ my $n = $q->param('n');
+
+ my ( $lat, $lon ) = Utils::convert_en_to_latlon_truncated( $e, $n );
+
+ my $lat_lon_url = NewURL(
+ $q,
+ -retain => 1,
+ e => undef,
+ n => undef,
+ lat => $lat,
+ lon => $lon
+ );
+
+ print $q->redirect(
+ -location => $lat_lon_url,
+ -status => 301, # permanent
+ );
+
+ return '';
}
sub display_location {
my ($q, @errors) = @_;
my $cobrand = Page::get_cobrand($q);
- my @vars = qw(pc x y e n all_pins no_pins);
- my %input = map { $_ => $q->param($_) || '' } @vars;
- my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
+ my @vars = qw(pc x y lat lon all_pins no_pins);
+
+ my %input = ();
+ my %input_h = ();
+
+ foreach my $key (@vars) {
+ my $val = $q->param($key);
+ $input{$key} = defined($val) ? $val : ''; # '0' is valid for longitude
+ $input_h{$key} = ent( $input{$key} );
+ }
- (my $easting) = $input{e} =~ /^(\d+)/; $easting ||= 0;
- (my $northing) = $input{n} =~ /^(\d+)/; $northing ||= 0;
+ my $latitude = $input{lat};
+ my $longitude = $input{lon};
# X/Y referring to tiles old-school
(my $x) = $input{x} =~ /^(\d+)/; $x ||= 0;
(my $y) = $input{y} =~ /^(\d+)/; $y ||= 0;
- return front_page($q, @errors) unless $x || $y || $input{pc} || $easting || $northing;
- if ($x && $y) {
+ return front_page( $q, @errors )
+ unless ( $x && $y )
+ || $input{pc}
+ || ( defined $latitude && defined $longitude );
+
+ if ( $x && $y ) {
+
# Convert the tile co-ordinates to real ones.
- $easting = FixMyStreet::Map::tile_to_os($x);
- $northing = FixMyStreet::Map::tile_to_os($y);
- } elsif ($easting && $northing) {
+ ( $latitude, $longitude ) =
+ FixMyStreet::Map::tile_xy_to_wgs84( $x, $y );
+ }
+ elsif ( $latitude && $longitude ) {
+
# Don't need to do anything
- } else {
+ }
+ else {
my $error;
try {
- ($easting, $northing, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
- } catch Error::Simple with {
+ ( $latitude, $longitude, $error ) =
+ FixMyStreet::Geocode::lookup( $input{pc}, $q );
+
+ debug 'Looked up postcode "%s": lat: "%s", lon: "%s", error: "%s"',
+ $input{pc}, $latitude, $longitude, $error;
+ }
+ catch Error::Simple with {
$error = shift;
};
- return FixMyStreet::Geocode::list_choices($error, '/', $q) if (ref($error) eq 'ARRAY');
- return front_page($q, $error) if $error;
+ return FixMyStreet::Geocode::list_choices( $error, '/', $q )
+ if ( ref($error) eq 'ARRAY' );
+ return front_page( $q, $error ) if $error;
}
# Check this location is okay to be displayed for the cobrand
- my ($success, $error_msg) = Cobrand::council_check($cobrand, { e => $easting, n => $northing }, $q, 'display_location');
+ my ($success, $error_msg) = Cobrand::council_check($cobrand, { lat => $latitude, lon => $longitude }, $q, 'display_location');
return front_page($q, $error_msg) unless $success;
# Deal with pin hiding/age
@@ -810,14 +889,14 @@ sub display_location {
$interval = '6 months';
}
- my ($on_map_all, $on_map, $around_map, $dist) = FixMyStreet::Map::map_features($q, $easting, $northing, $interval);
+ my ($on_map_all, $on_map, $around_map, $dist) = FixMyStreet::Map::map_features($q, $latitude, $longitude, $interval);
my @pins;
foreach (@$on_map_all) {
- push @pins, [ $_->{easting}, $_->{northing}, $_->{state} eq 'fixed' ? 'green' : 'red' ];
+ push @pins, [ $_->{latitude}, $_->{longitude}, ($_->{state} eq 'fixed' ? 'green' : 'red'), $_->{id} ];
}
my $on_list = '';
foreach (@$on_map) {
- my $report_url = NewURL($q, -retain => 1, -url => '/report/' . $_->{id}, pc => undef, x => undef, 'y' => undef);
+ my $report_url = NewURL($q, -url => '/report/' . $_->{id});
$report_url = Cobrand::url($cobrand, $report_url, $q);
$on_list .= '<li><a href="' . $report_url . '">';
$on_list .= ent($_->{title}) . '</a> <small>(';
@@ -830,16 +909,16 @@ sub display_location {
my $around_list = '';
foreach (@$around_map) {
- my $report_url = Cobrand::url($cobrand, NewURL($q, -retain => 1, -url => '/report/' . $_->{id}, pc => undef, x => undef, 'y' => undef), $q);
+ my $report_url = Cobrand::url($cobrand, NewURL($q, -url => '/report/' . $_->{id}), $q);
$around_list .= '<li><a href="' . $report_url . '">';
- my $dist = int($_->{distance}/100+0.5);
+ my $dist = int($_->{distance}*10+0.5);
$dist = $dist / 10;
$around_list .= ent($_->{title}) . '</a> <small>(';
$around_list .= Page::prettify_epoch($q, $_->{time}, 1) . ', ';
$around_list .= $dist . 'km)</small>';
$around_list .= ' <small>' . _('(fixed)') . '</small>' if $_->{state} eq 'fixed';
$around_list .= '</li>';
- push @pins, [ $_->{easting}, $_->{northing}, $_->{state} eq 'fixed' ? 'green' : 'red' ];
+ push @pins, [ $_->{latitude}, $_->{longitude}, ($_->{state} eq 'fixed' ? 'green' : 'red'), $_->{id} ];
}
$around_list = $q->li(_('No problems found.'))
unless $around_list;
@@ -852,25 +931,44 @@ sub display_location {
$hide_link = NewURL($q, -retain=>1, no_pins=>1);
$hide_text = _('Hide pins');
}
- my $map_links = "<p id='sub_map_links'><a id='hide_pins_link' rel='nofollow' href='$hide_link'>$hide_text</a> | <a id='all_pins_link' rel='nofollow' href='$all_link'>$all_text</a></p> <input type='hidden' id='all_pins' name='all_pins' value='$input_h{all_pins}'>";
+ my $map_links = "<p id='sub_map_links'><a id='hide_pins_link' rel='nofollow' href='$hide_link'>$hide_text</a>";
+ if (mySociety::Config::get('COUNTRY') eq 'GB') {
+ $map_links .= " | <a id='all_pins_link' rel='nofollow' href='$all_link'>$all_text</a></p> <input type='hidden' id='all_pins' name='all_pins' value='$input_h{all_pins}'>";
+ } else {
+ $map_links .= "</p>";
+ }
- my $url_skip = NewURL($q, -retain=>1, pc => undef,
+ # truncate the lat,lon for nicer rss urls, and strings for outputting
+ my ( $short_lat, $short_lon ) =
+ map { Utils::truncate_coordinate($_) } #
+ ( $latitude, $longitude );
+
+ my $url_skip = NewURL($q, -retain=>1,
x => undef, 'y' => undef,
- easting => $easting, northing => $northing,
+ latitude => $short_lat, longitude => $short_lon,
'submit_map'=>1, skipped=>1
);
my $pc_h = ent($q->param('pc') || '');
+
+ my $rss_url;
+ if ($pc_h) {
+ $rss_url = "/rss/pc/" . URI::Escape::uri_escape_utf8($pc_h);
+ } else {
+ $rss_url = "/rss/l/$short_lat,$short_lon";
+ }
+ $rss_url = Cobrand::url( $cobrand, NewURL($q, -url=> $rss_url), $q);
+
my %vars = (
'map' => FixMyStreet::Map::display_map($q,
- easting => $easting, northing => $northing,
+ latitude => $short_lat, longitude => $short_lon,
type => 1,
pins => \@pins,
post => $map_links
),
map_end => FixMyStreet::Map::display_map_end(1),
url_home => Cobrand::url($cobrand, '/', $q),
- url_rss => Cobrand::url($cobrand, NewURL($q, -retain => 1, -url=> "/rss/n/$easting,$northing", pc => undef, x => undef, 'y' => undef), $q),
- url_email => Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, -url=>'/alert', e=>$easting, 'n'=>$northing, feed=>"local:$easting:$northing"), $q),
+ url_rss => $rss_url,
+ url_email => Cobrand::url($cobrand, NewURL($q, lat => $short_lat, lon => $short_lon, -url=>'/alert', feed=>"local:$short_lat:$short_lon"), $q),
url_skip => $url_skip,
email_me => _('Email me new local problems'),
rss_alt => _('RSS feed'),
@@ -890,7 +988,8 @@ sub display_location {
);
my %params = (
- rss => [ _('Recent local problems, FixMyStreet'), "/rss/n/$easting,$northing" ],
+ rss => [ _('Recent local problems, FixMyStreet'), $rss_url ],
+ js => FixMyStreet::Map::header_js(),
robots => 'noindex,nofollow',
);
@@ -931,9 +1030,18 @@ sub display_problem {
my $extra_data = Cobrand::extra_data($cobrand, $q);
my $google_link = Cobrand::base_url_for_emails($cobrand, $extra_data)
. '/report/' . $problem->{id};
- my ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($problem->{easting}, $problem->{northing}, 'G');
- my $map_links = "<p id='sub_map_links'><a href=\"http://maps.google.co.uk/maps?output=embed&amp;z=16&amp;q="
- . URI::Escape::uri_escape_utf8($problem->{title} . ' - ' . $google_link) . "\@$lat,$lon\">View on Google Maps</a></p>";
+
+ # truncate the lat,lon for nicer rss urls
+ my ( $short_lat, $short_lon ) =
+ map { Utils::truncate_coordinate($_) } #
+ ( $problem->{latitude}, $problem->{longitude} );
+
+ my $map_links = '';
+ $map_links = "<p id='sub_map_links'>"
+ . "<a href=\"http://maps.google.co.uk/maps?output=embed&amp;z=16&amp;q="
+ . URI::Escape::uri_escape_utf8( $problem->{title} . ' - ' . $google_link )
+ . "\@$short_lat,$short_lon\">View on Google Maps</a></p>"
+ if mySociety::Config::get('COUNTRY') eq 'GB';
my $banner;
if ($q->{site} ne 'emptyhomes' && $problem->{state} eq 'confirmed' && $problem->{duration} > 8*7*24*60*60) {
@@ -945,7 +1053,7 @@ sub display_problem {
my $contact_url = Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, x => undef, 'y' => undef, -url=>'/contact?id=' . $input{id}), $q);
my $back = Cobrand::url($cobrand, NewURL($q, -url => '/',
- 'e' => int($problem->{easting}), 'n' => int($problem->{northing}),
+ lat => $short_lat, lon => $short_lon,
-retain => 1, pc => undef, x => undef, 'y' => undef, id => undef
), $q);
my $fixed = ($input{fixed}) ? ' checked' : '';
@@ -953,9 +1061,9 @@ sub display_problem {
my %vars = (
banner => $banner,
map_start => FixMyStreet::Map::display_map($q,
- easting => $problem->{easting}, northing => $problem->{northing},
+ latitude => $problem->{latitude}, longitude => $problem->{longitude},
type => 0,
- pins => [ [ $problem->{easting}, $problem->{northing}, 'blue' ] ],
+ pins => $problem->{used_map} ? [ [ $problem->{latitude}, $problem->{longitude}, 'blue' ] ] : [],
post => $map_links
),
map_end => FixMyStreet::Map::display_map_end(0),
@@ -989,6 +1097,7 @@ sub display_problem {
cobrand_form_elements => Cobrand::form_elements($cobrand, 'updateForm', $q),
form_action => Cobrand::url($cobrand, '/', $q),
input_h => \%input_h,
+ optional => _('(optional)'),
);
$vars{update_blurb} = $q->p($q->small(_('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>')))
@@ -1013,6 +1122,7 @@ EOF
my %params = (
rss => [ _('Updates to this problem, FixMyStreet'), "/rss/$input_h{id}" ],
robots => 'index, nofollow',
+ js => FixMyStreet::Map::header_js(),
title => $problem->{title}
);
diff --git a/web/js.js b/web/js.js
index b2012fc84..07bede2d7 100644
--- a/web/js.js
+++ b/web/js.js
@@ -16,8 +16,12 @@ YAHOO.util.Event.onContentReady('mapForm', function() {
this.onsubmit = function() { return false; };
}
- this.x.value = fixmystreet.x + 3;
- this.y.value = fixmystreet.y + 3;
+ /* XXX Should be in Tilma code only */
+ if (this.x) {
+ this.x.value = fixmystreet.x + 3;
+ this.y.value = fixmystreet.y + 3;
+ }
+
/*
if (swfu && swfu.getStats().files_queued > 0) {
swfu.startUpload();
diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js
new file mode 100644
index 000000000..1134bafb7
--- /dev/null
+++ b/web/js/map-OpenLayers.js
@@ -0,0 +1,182 @@
+YAHOO.util.Event.onContentReady('map', function() {
+
+ fixmystreet.ZOOM_OFFSET = 14;
+
+ var perm = new OpenLayers.Control.Permalink();
+ set_map_config(perm);
+
+ fixmystreet.map = new OpenLayers.Map("map", {
+ controls: fixmystreet.controls,
+ displayProjection: new OpenLayers.Projection("EPSG:4326")
+ });
+
+ fixmystreet.layer_options = OpenLayers.Util.extend({
+ zoomOffset: fixmystreet.ZOOM_OFFSET,
+ transitionEffect: 'resize',
+ numZoomLevels: 4
+ }, fixmystreet.layer_options);
+ var layer = new fixmystreet.map_type("", fixmystreet.layer_options);
+ fixmystreet.map.addLayer(layer);
+
+ if (!fixmystreet.map.getCenter()) {
+ var centre = new OpenLayers.LonLat( fixmystreet.longitude, fixmystreet.latitude );
+ centre.transform(
+ new OpenLayers.Projection("EPSG:4326"),
+ fixmystreet.map.getProjectionObject()
+ );
+ fixmystreet.map.setCenter(centre, 2);
+ }
+
+ if (document.getElementById('mapForm')) {
+ var click = new OpenLayers.Control.Click();
+ fixmystreet.map.addControl(click);
+ click.activate();
+ }
+
+ /* To let permalink not be caught by the Click layer, answer found
+ * at http://www.mail-archive.com/users@openlayers.org/msg12958.html
+ * Not sure why you can't use eventListeners or events.register...
+ */
+ OpenLayers.Event.observe( perm.element, "click", function(e) {
+ OpenLayers.Event.stop(e);
+ location.href = OpenLayers.Event.element(e).href;
+ return false;
+ });
+
+ fixmystreet.markers = new OpenLayers.Layer.Markers("Markers");
+ var cols = { 'red':'R', 'green':'G', 'blue':'B', 'purple':'P' };
+ for (var i=0; i<fixmystreet.pins.length; i++) {
+ var pin = fixmystreet.pins[i];
+ var src = '/i/pin' + cols[pin[2]] + '.gif';
+ var size = new OpenLayers.Size(32, 59);
+ var offset = new OpenLayers.Pixel(-3, -size.h-2);
+ var icon = new OpenLayers.Icon(src, size, offset);
+ var loc = new OpenLayers.LonLat(pin[1], pin[0]);
+ loc.transform(
+ new OpenLayers.Projection("EPSG:4326"),
+ fixmystreet.map.getProjectionObject()
+ );
+ var marker = new OpenLayers.Marker(loc, icon);
+ if (pin[3]) {
+ marker.id = pin[3];
+ marker.events.register('click', marker, function(evt) {
+ window.location = '/report/' + this.id;
+ OpenLayers.Event.stop(evt);
+ });
+ }
+ fixmystreet.markers.addMarker(marker);
+ }
+ fixmystreet.map.addLayer(fixmystreet.markers);
+
+});
+
+YAHOO.util.Event.addListener('hide_pins_link', 'click', function(e) {
+ YAHOO.util.Event.preventDefault(e);
+ var showhide = [
+ 'Show pins', 'Hide pins',
+ 'Dangos pinnau', 'Cuddio pinnau',
+ "Vis nåler", "Gjem nåler"
+ ];
+ for (var i=0; i<showhide.length; i+=2) {
+ if (this.innerHTML == showhide[i]) {
+ fixmystreet.markers.setVisibility(true);
+ this.innerHTML = showhide[i+1];
+ } else if (this.innerHTML == showhide[i+1]) {
+ fixmystreet.markers.setVisibility(false);
+ this.innerHTML = showhide[i];
+ }
+ }
+});
+
+/* Overridding the buttonDown function of PanZoom so that it does
+ zoomTo(0) rather than zoomToMaxExtent()
+*/
+OpenLayers.Control.PanZoomFMS = OpenLayers.Class(OpenLayers.Control.PanZoom, {
+ buttonDown: function (evt) {
+ if (!OpenLayers.Event.isLeftClick(evt)) {
+ return;
+ }
+
+ switch (this.action) {
+ case "panup":
+ this.map.pan(0, -this.getSlideFactor("h"));
+ break;
+ case "pandown":
+ this.map.pan(0, this.getSlideFactor("h"));
+ break;
+ case "panleft":
+ this.map.pan(-this.getSlideFactor("w"), 0);
+ break;
+ case "panright":
+ this.map.pan(this.getSlideFactor("w"), 0);
+ break;
+ case "zoomin":
+ this.map.zoomIn();
+ break;
+ case "zoomout":
+ this.map.zoomOut();
+ break;
+ case "zoomworld":
+ this.map.zoomTo(0);
+ break;
+ }
+
+ OpenLayers.Event.stop(evt);
+ }
+});
+
+/* Overriding Permalink so that it can pass the correct zoom to OSM */
+OpenLayers.Control.PermalinkFMS = OpenLayers.Class(OpenLayers.Control.Permalink, {
+ updateLink: function() {
+ var separator = this.anchor ? '#' : '?';
+ var href = this.base;
+ if (href.indexOf(separator) != -1) {
+ href = href.substring( 0, href.indexOf(separator) );
+ }
+
+ href += separator + OpenLayers.Util.getParameterString(this.createParams(null, this.map.getZoom()+fixmystreet.ZOOM_OFFSET));
+ if (this.anchor && !this.element) {
+ window.location.href = href;
+ }
+ else {
+ this.element.href = href;
+ }
+ }
+});
+
+/* Click handler */
+OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
+ defaultHandlerOptions: {
+ 'single': true,
+ 'double': false,
+ 'pixelTolerance': 0,
+ 'stopSingle': false,
+ 'stopDouble': false
+ },
+
+ initialize: function(options) {
+ this.handlerOptions = OpenLayers.Util.extend(
+ {}, this.defaultHandlerOptions
+ );
+ OpenLayers.Control.prototype.initialize.apply(
+ this, arguments
+ );
+ this.handler = new OpenLayers.Handler.Click(
+ this, {
+ 'click': this.trigger
+ }, this.handlerOptions
+ );
+ },
+
+ trigger: function(e) {
+ var lonlat = fixmystreet.map.getLonLatFromViewPortPx(e.xy);
+ lonlat.transform(
+ fixmystreet.map.getProjectionObject(),
+ new OpenLayers.Projection("EPSG:4326")
+ );
+ document.getElementById('fixmystreet.latitude').value = lonlat.lat;
+ document.getElementById('fixmystreet.longitude').value = lonlat.lon;
+ document.getElementById('mapForm').submit();
+ }
+});
+
diff --git a/web/js/map-OpenStreetMap.js b/web/js/map-OpenStreetMap.js
index 04237e075..9d226f6a7 100644
--- a/web/js/map-OpenStreetMap.js
+++ b/web/js/map-OpenStreetMap.js
@@ -1,27 +1,13 @@
-YAHOO.util.Event.onContentReady('map', function() {
- var map = new OpenLayers.Map("map", {
- controls: [
- new OpenLayers.Control.ArgParser(),
- //new OpenLayers.Control.LayerSwitcher(),
- new OpenLayers.Control.Navigation(),
- new OpenLayers.Control.PanZoom()
- ],
- displayProjection: new OpenLayers.Projection("EPSG:4326")
- });
- var streetview = new fixmystreet.map_type("", {
- zoomOffset: 14,
- numZoomLevels: 4
- });
- map.addLayer(streetview);
-
- var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing );
- centre.transform(
- new OpenLayers.Projection("EPSG:27700"),
- map.getProjectionObject()
- );
- map.setCenter(centre, 2);
-});
-
+function set_map_config(perm) {
+ fixmystreet.controls = [
+ new OpenLayers.Control.ArgParser(),
+ //new OpenLayers.Control.LayerSwitcher(),
+ new OpenLayers.Control.Navigation(),
+ perm,
+ new OpenLayers.Control.PermalinkFMS('osm_link', 'http://www.openstreetmap.org/'),
+ new OpenLayers.Control.PanZoomFMS()
+ ];
+}
// http://www.openstreetmap.org/openlayers/OpenStreetMap.js (added maxResolution)
diff --git a/web/js/map-bing-ol.js b/web/js/map-bing-ol.js
index ba9445326..254d407f4 100644
--- a/web/js/map-bing-ol.js
+++ b/web/js/map-bing-ol.js
@@ -1,33 +1,13 @@
-YAHOO.util.Event.onContentReady('map', function() {
- var map = new OpenLayers.Map("map", {
- controls: [
- new OpenLayers.Control.ArgParser(),
- //new OpenLayers.Control.LayerSwitcher(),
- new OpenLayers.Control.Navigation(),
- new OpenLayers.Control.PanZoom()
- ],
- displayProjection: new OpenLayers.Projection("EPSG:4326")
- });
- var bing = new OpenLayers.Layer.Bing("", {
- zoomOffset: 13,
- numZoomLevels: 4
- });
- map.addLayer(bing);
-
- var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing );
- centre.transform(
- new OpenLayers.Projection("EPSG:27700"),
- map.getProjectionObject()
- );
- map.setCenter(centre, 3);
-});
-
-OpenLayers.Util.OS = {};
-OpenLayers.Util.OS.MISSING_TILE_URL = "http://openstreetmap.org/openlayers/img/404.png";
-OpenLayers.Util.OS.originalOnImageLoadError = OpenLayers.Util.onImageLoadError;
-OpenLayers.Util.onImageLoadError = function() {
- OpenLayers.Util.OS.originalOnImageLoadError;
-};
+function set_map_config(perm) {
+ fixmystreet.ZOOM_OFFSET = 13;
+ fixmystreet.controls = [
+ new OpenLayers.Control.ArgParser(),
+ new OpenLayers.Control.Navigation(),
+ perm,
+ new OpenLayers.Control.PanZoomFMS()
+ ];
+ fixmystreet.map_type = OpenLayers.Layer.Bing;
+}
OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {
initialize: function(name, options) {
@@ -38,6 +18,7 @@ OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {
numZoomLevels: 18,
transitionEffect: "resize",
sphericalMercator: true,
+ buffer: 0,
attribution: "© Microsoft / OS 2010"
}, options);
var newArguments = [name, url, options];
diff --git a/web/js/map-bing.js b/web/js/map-bing.js
index fbbbcc676..748a03525 100644
--- a/web/js/map-bing.js
+++ b/web/js/map-bing.js
@@ -1,6 +1,7 @@
YAHOO.util.Event.onContentReady('map', function() {
- var centre = new Microsoft.Maps.Location( fixmystreet.lat, fixmystreet.lon );
+ var centre = new Microsoft.Maps.Location( fixmystreet.latitude, fixmystreet.longitude );
var map = new Microsoft.Maps.Map(document.getElementById("map"), {
+ credentials: fixmystreet.key,
mapTypeId: Microsoft.Maps.MapTypeId.ordnanceSurvey,
center: centre,
zoom: 15,
diff --git a/web/js/map-google.js b/web/js/map-google.js
index 77e54ab7c..ab9bb9042 100644
--- a/web/js/map-google.js
+++ b/web/js/map-google.js
@@ -1,5 +1,5 @@
YAHOO.util.Event.onContentReady('map', function() {
- var centre = new google.maps.LatLng( fixmystreet.lat, fixmystreet.lon );
+ var centre = new google.maps.LatLng( fixmystreet.latitude, fixmystreet.longitude );
var map = new google.maps.Map(document.getElementById("map"), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: centre,
diff --git a/web/js/map-streetview.js b/web/js/map-streetview.js
index 088e5b6a2..cfd595b95 100644
--- a/web/js/map-streetview.js
+++ b/web/js/map-streetview.js
@@ -1,27 +1,13 @@
-YAHOO.util.Event.onContentReady('map', function() {
- var map = new OpenLayers.Map("map", {
- controls: [
- new OpenLayers.Control.ArgParser(),
- //new OpenLayers.Control.LayerSwitcher(),
- new OpenLayers.Control.Navigation(),
- new OpenLayers.Control.PanZoom()
- ],
- displayProjection: new OpenLayers.Projection("EPSG:4326")
- });
- var streetview = new OpenLayers.Layer.StreetView("OS StreetView (1:10000)", {
- zoomOffset: 14,
- numZoomLevels: 4
- });
- map.addLayer(streetview);
-
- var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing );
- centre.transform(
- new OpenLayers.Projection("EPSG:27700"),
- map.getProjectionObject()
- );
- map.setCenter(centre, 2);
-});
-
+function set_map_config(perm) {
+ fixmystreet.controls = [
+ new OpenLayers.Control.ArgParser(),
+ //new OpenLayers.Control.LayerSwitcher(),
+ new OpenLayers.Control.Navigation(),
+ perm,
+ new OpenLayers.Control.PanZoomFMS()
+ ];
+ fixmystreet.map_type = OpenLayers.Layer.StreetView;
+}
// http://os.openstreetmap.org/openlayers/OS.js (added one line)
diff --git a/web/js/map-tilma-ol.js b/web/js/map-tilma-ol.js
index cfd196c1d..5230a5d2c 100644
--- a/web/js/map-tilma-ol.js
+++ b/web/js/map-tilma-ol.js
@@ -1,21 +1,19 @@
-YAHOO.util.Event.onContentReady('map', function() {
- var map = new OpenLayers.Map("map", {
- controls: [
- new OpenLayers.Control.ArgParser(),
- new OpenLayers.Control.Navigation(),
- new OpenLayers.Control.PanPanel()
- ]
- });
- var tilma = new OpenLayers.Layer.Tilma("Tilma", {
+function set_map_config(perm) {
+ fixmystreet.controls = [
+ new OpenLayers.Control.ArgParser(),
+ perm,
+ new OpenLayers.Control.Navigation(),
+ new OpenLayers.Control.PanPanel()
+ ];
+ fixmystreet.map_type = OpenLayers.Layer.Tilma;
+ fixmystreet.layer_options = {
maxResolution: fixmystreet.maxResolution,
tileSize: new OpenLayers.Size(fixmystreet.tilewidth, fixmystreet.tileheight),
- map_type: fixmystreet.tile_type
- });
- map.addLayer(tilma);
-
- var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing );
- map.setCenter(centre);
-});
+ map_type: fixmystreet.tile_type,
+ numZoomLevels: 1,
+ zoomOffset: 0
+ };
+}
OpenLayers.Layer.Tilma = OpenLayers.Class(OpenLayers.Layer.XYZ, {
initialize: function(name, options) {
@@ -23,8 +21,9 @@ OpenLayers.Layer.Tilma = OpenLayers.Class(OpenLayers.Layer.XYZ, {
options = OpenLayers.Util.extend({
transitionEffect: "resize",
numZoomLevels: 1,
+ projection: "EPSG:27700",
units: "m",
- maxExtent: new OpenLayers.Bounds(0, 0, 700000, 1300000),
+ maxExtent: new OpenLayers.Bounds(0, 0, 700000, 1300000)
}, options);
var newArguments = [name, url, options];
OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArguments);
diff --git a/web/js/map-tilma.js b/web/js/map-tilma.js
index 1ae38cff1..1b8cc6450 100644
--- a/web/js/map-tilma.js
+++ b/web/js/map-tilma.js
@@ -135,7 +135,7 @@ function update_tiles(dx, dy, force) {
}
function load_pins(x, y) {
- if (document.getElementById('formX')) {
+ if (document.getElementById('formX') && !document.getElementById('problem_submit')) {
all_pins = '';
if (document.getElementById('all_pins')) {
all_pins = document.getElementById('all_pins').value;
diff --git a/web/photo.cgi b/web/photo.cgi
index fc89fc0f7..bd38e3bf1 100755
--- a/web/photo.cgi
+++ b/web/photo.cgi
@@ -39,7 +39,7 @@ sub main {
print $photo;
}
-Page::do_fastcgi(\&main);
+Page::do_fastcgi(\&main, 0, 1);
sub resize {
my ($photo, $size) = @_;
diff --git a/web/questionnaire.cgi b/web/questionnaire.cgi
index 33e823560..fdb1c08a4 100755
--- a/web/questionnaire.cgi
+++ b/web/questionnaire.cgi
@@ -25,7 +25,10 @@ sub main {
} else {
$out = display_questionnaire($q);
}
- print Page::header($q, title=>_('Questionnaire'));
+ print Page::header($q,
+ title => _('Questionnaire'),
+ js => FixMyStreet::Map::header_js(),
+ );
print $out;
print Page::footer($q);
}
@@ -220,9 +223,9 @@ sub display_questionnaire {
my %vars = (
input_h => \%input_h,
map_start => FixMyStreet::Map::display_map($q,
- easting => $problem->{easting}, northing => $problem->{northing},
+ latitude => $problem->{latitude}, longitude => $problem->{longitude},
pins => [
- [ $problem->{easting}, $problem->{northing}, $problem->{state} eq 'fixed'?'green':'red' ],
+ [ $problem->{latitude}, $problem->{longitude}, $problem->{state} eq 'fixed'?'green':'red' ],
],
pre => $problem_text, post => $updates
),
@@ -302,9 +305,10 @@ EOF
(please note it will not be sent to the council). For example, what was
your experience of getting the problem fixed?'));
if ($allow_photo_upload) {
- $vars{photo_input} = <<EOF;
+ my $photo = _('Photo:');
+ $vars{photo_input} = <<EOF;
<div id="fileupload_normalUI">
-<label for="form_photo">Photo:</label>
+<label for="form_photo">$photo</label>
<input type="file" name="photo" id="form_photo">
</div>
EOF
@@ -315,14 +319,17 @@ EOF
);
$vars{another_yes} = $another{yes};
$vars{another_no} = $another{no};
+ my $another_qn = _('Would you like to receive another questionnaire in 4 weeks, reminding you to check the status?');
+ my $yes = _('Yes');
+ my $no = _('No');
$vars{another_questionnaire} = <<EOF if $q->{site} ne 'emptyhomes';
<div id="another_qn">
-<p>Would you like to receive another questionnaire in 4 weeks, reminding you to check the status?</p>
+<p>$another_qn</p>
<p>
<input type="radio" name="another" id="another_yes" value="Yes"$another{yes}>
-<label for="another_yes">Yes</label>
+<label for="another_yes">$yes</label>
<input type="radio" name="another" id="another_no" value="No"$another{no}>
-<label for="another_no">No</label>
+<label for="another_no">$no</label>
</p>
</div>
EOF
diff --git a/web/reports.cgi b/web/reports.cgi
index fe4213be4..22dbe344a 100755
--- a/web/reports.cgi
+++ b/web/reports.cgi
@@ -11,6 +11,8 @@
use strict;
use Standard;
+use Encode;
+use POSIX qw(strcoll);
use URI::Escape;
use FixMyStreet::Alert;
use mySociety::MaPit;
@@ -22,9 +24,11 @@ sub main {
my $all = $q->param('all') || 0;
my $rss = $q->param('rss') || '';
my $cobrand = Page::get_cobrand($q);
+
# Look up council name, if given
my $q_council = $q->param('council') || '';
my $base_url = Cobrand::base_url($cobrand);
+
# Manual misspelling redirect
if ($q_council =~ /^rhondda cynon taff$/i) {
print $q->redirect($base_url . '/reports/Rhondda+Cynon+Taf');
@@ -38,24 +42,49 @@ sub main {
print $q->redirect($base_url . '/reports');
return;
}
- $area_name = Page::short_name($va_info->{name});
+ $area_name = Page::short_name($va_info);
if (length($q_council) == 6) {
$va_info = mySociety::MaPit::call('area', $va_info->{parent_area});
- $area_name = Page::short_name($va_info->{name}) . '/' . $area_name;
+ $area_name = Page::short_name($va_info) . '/' . $area_name;
}
$rss = '/rss' if $rss;
print $q->redirect($base_url . $rss . '/reports/' . $area_name);
return;
+ } elsif (mySociety::Config::get('COUNTRY') eq 'NO' && $q_council eq 'Oslo') {
+ $one_council = mySociety::MaPit::call('area', 3);
+ $area_type = $one_council->{type};
+ $area_name = $one_council->{name};
+ } elsif (mySociety::Config::get('COUNTRY') eq 'NO' && $q_council =~ /,/) {
+ my ($kommune, $fylke) = split /\s*,\s*/, $q_council;
+ my @area_types = Cobrand::area_types($cobrand);
+ my $areas_k = mySociety::MaPit::call('areas', $kommune, type => \@area_types);
+ my $areas_f = mySociety::MaPit::call('areas', $fylke, type => \@area_types);
+ if (keys %$areas_f == 1) {
+ ($fylke) = values %$areas_f;
+ foreach (values %$areas_k) {
+ if ($_->{name} eq $kommune && $_->{parent_area} == $fylke->{id}) {
+ $one_council = $_;
+ $area_type = $_->{type};
+ $area_name = $_->{name};
+ last;
+ }
+ }
+ }
+ if (!$one_council) { # Given a false council name
+ print $q->redirect($base_url . '/reports');
+ return;
+ }
} elsif ($q_council =~ /\D/) {
- my $areas = mySociety::MaPit::call('areas', $q_council, type => $mySociety::VotingArea::council_parent_types, min_generation=>10 );
+ my @area_types = Cobrand::area_types($cobrand);
+ my $areas = mySociety::MaPit::call('areas', $q_council, type => \@area_types, min_generation=>Cobrand::area_min_generation($cobrand) );
if (keys %$areas == 1) {
- ($one_council) = keys %$areas;
- $area_type = $areas->{$one_council}->{type};
- $area_name = $areas->{$one_council}->{name};
+ ($one_council) = values %$areas;
+ $area_type = $one_council->{type};
+ $area_name = $one_council->{name};
} else {
foreach (keys %$areas) {
- if ($areas->{$_}->{name} =~ /^\Q$q_council\E (Borough|City|District|County) Council$/) {
- $one_council = $_;
+ if ($areas->{$_}->{name} eq $q_council || $areas->{$_}->{name} =~ /^\Q$q_council\E (Borough|City|District|County) Council$/) {
+ $one_council = $areas->{$_};
$area_type = $areas->{$_}->{type};
$area_name = $q_council;
}
@@ -71,8 +100,7 @@ sub main {
print $q->redirect($base_url . '/reports');
return;
}
- $area_name = $va_info->{name};
- print $q->redirect($base_url . '/reports/' . Page::short_name($area_name));
+ print $q->redirect($base_url . '/reports/' . Page::short_name($va_info));
return;
}
$all = 0 unless $one_council;
@@ -81,23 +109,24 @@ sub main {
my $q_ward = $q->param('ward') || '';
my $ward;
if ($one_council && $q_ward) {
- my $qw = mySociety::MaPit::call('areas', $q_ward, type => $mySociety::VotingArea::council_child_types, min_generation => 10);
+ my $qw = mySociety::MaPit::call('areas', $q_ward, type => $mySociety::VotingArea::council_child_types,
+ min_generation => Cobrand::area_min_generation($cobrand));
foreach my $id (sort keys %$qw) {
- if ($qw->{$id}->{parent_area} == $one_council) {
- $ward = $id;
+ if ($qw->{$id}->{parent_area} == $one_council->{id}) {
+ $ward = $qw->{$id};
last;
}
}
if (!$ward) { # Given a false ward name
- print $q->redirect($base_url . '/reports/' . Page::short_name($q_council));
+ print $q->redirect($base_url . '/reports/' . Page::short_name($one_council));
return;
}
}
# RSS - reports for sent reports, area for all problems in area
if ($rss && $one_council) {
- my $url = Page::short_name($q_council);
- $url .= '/' . Page::short_name($q_ward) if $ward;
+ my $url = Page::short_name($one_council);
+ $url .= '/' . Page::short_name($ward) if $ward;
if ($rss eq 'area' && $area_type ne 'DIS' && $area_type ne 'CTY') {
# Two possibilites are the same for one-tier councils, so redirect one to the other
print $q->redirect($base_url . '/rss/reports/' . $url);
@@ -106,8 +135,8 @@ sub main {
my $type = 'council_problems'; # Problems sent to a council
my (@params, %title_params);
$title_params{COUNCIL} = $area_name;
- push @params, $one_council if $rss eq 'reports';
- push @params, $ward ? $ward : $one_council;
+ push @params, $one_council->{id} if $rss eq 'reports';
+ push @params, $ward ? $ward->{id} : $one_council->{id};
if ($ward && $rss eq 'reports') {
$type = 'ward_problems'; # Problems sent to a council, restricted to a ward
$title_params{WARD} = $q_ward;
@@ -125,16 +154,20 @@ sub main {
my $areas_info;
if ($one_council) {
- $areas_info = mySociety::MaPit::call('areas', $one_council);
+ $areas_info = mySociety::MaPit::call('areas', [ $one_council->{id}, $one_council->{parent_area} ])
+ if $one_council->{parent_area};
+ $areas_info = { $one_council->{id} => $one_council }
+ unless $areas_info;
} else {
# Show all councils on main report page
- my $ignore = 'LGD';
- $ignore .= '|CTY' if $q->{site} eq 'emptyhomes';
- my @types = grep { !/$ignore/ } @$mySociety::VotingArea::council_parent_types;
- $areas_info = mySociety::MaPit::call('areas', [ @types ], min_generation=>10 );
+ my @area_types = Cobrand::area_types($cobrand);
+ $areas_info = mySociety::MaPit::call('areas', \@area_types, min_generation=>Cobrand::area_min_generation($cobrand) );
}
- my $problems = Problems::council_problems($ward, $one_council);
+ my $problems = Problems::council_problems(
+ $ward ? $ward->{id} : undef,
+ $one_council ? $one_council->{id} : undef
+ );
my (%fixed, %open);
my $re_councils = join('|', keys %$areas_info);
@@ -149,7 +182,7 @@ sub main {
$row->{council} =~ s/\|.*$//;
my @council = split /,/, $row->{council};
foreach (@council) {
- next if $one_council && $_ != $one_council;
+ next if $one_council && $_ != $one_council->{id};
add_row($row, scalar @council, $_, \%fixed, \%open);
}
}
@@ -168,18 +201,23 @@ sub main {
print '<th>' . _('Old problems,<br>state unknown') . '</th>';
}
print '<th>' . _('Recently fixed') . '</th><th>' . _('Older fixed') . '</th></tr>';
- foreach (sort { $areas_info->{$a}->{name} cmp $areas_info->{$b}->{name} } keys %$areas_info) {
+ foreach (sort { strcoll($areas_info->{$a}->{name}, $areas_info->{$b}->{name}) } keys %$areas_info) {
+ next if mySociety::Config::get('COUNTRY') eq 'NO' && $_ eq 301; # Only want one Oslo
print '<tr align="center"';
++$c;
- if ($areas_info->{$_}->{generation_high}==10) {
+ if (mySociety::Config::get('COUNTRY') eq 'GB' && $areas_info->{$_}->{generation_high} == 10) {
print ' class="gone"';
} elsif ($c%2) {
print ' class="a"';
}
- my $url = Page::short_name($areas_info->{$_}->{name});
+ my $url = Page::short_name($areas_info->{$_}, $areas_info);
my $cobrand_url = Cobrand::url($cobrand, "/reports/$url", $q);
print '><td align="left"><a href="' . $cobrand_url . '">' .
- $areas_info->{$_}->{name} . '</a></td>';
+ $areas_info->{$_}->{name};
+ if ($areas_info->{$_}->{parent_area} && $url =~ /,|%2C/) {
+ print ', ' . $areas_info->{$areas_info->{$_}->{parent_area}}->{name};
+ }
+ print '</a></td>';
summary_cell(\@{$open{$_}{new}});
if ($q->{site} eq 'emptyhomes') {
my $c = 0;
@@ -196,17 +234,17 @@ sub main {
}
print '</table>';
} else {
- my $name = $areas_info->{$one_council}->{name};
+ my $name = $one_council->{name};
if (!$name) {
print Page::header($q, title=>_("Summary reports"));
- print "Council with identifier " . ent($one_council). " not found. ";
+ print "Council with identifier " . ent($one_council->{id}). " not found. ";
print $q->a({href => Cobrand::url($cobrand, '/reports', $q) }, 'Show all councils');
print ".";
} else {
- my $rss_url = '/rss/reports/' . Page::short_name($name);
+ my $rss_url = '/rss/reports/' . Page::short_name($one_council, $areas_info);
my $thing = _('council');
if ($ward) {
- $rss_url .= '/' . Page::short_name($q_ward);
+ $rss_url .= '/' . Page::short_name($ward);
$thing = 'ward';
$name = ent($q_ward) . ", $name";
}
@@ -232,24 +270,25 @@ sub main {
$vars{summary_line} = sprintf(_('You can <a href="%s">see more details</a> or go back and <a href="/reports">show all councils</a>.'), Cobrand::url($cobrand, NewURL($q, all=>1), $q));
}
- if ($open{$one_council}) {
- my $col = list_problems($q, _('New problems'), $open{$one_council}{new}, $all, 0);
+ my $id = $one_council->{id};
+ if ($open{$id}) {
+ my $col = list_problems($q, _('New problems'), $open{$id}{new}, $all, 0);
my $old = [];
if ($q->{site} eq 'emptyhomes') {
- push @$old, @{$open{$one_council}{older}} if $open{$one_council}{older};
- push @$old, @{$open{$one_council}{unknown}} if $open{$one_council}{unknown};
+ push @$old, @{$open{$id}{older}} if $open{$id}{older};
+ push @$old, @{$open{$id}{unknown}} if $open{$id}{unknown};
} else {
- $old = $open{$one_council}{older};
+ $old = $open{$id}{older};
}
$col .= list_problems($q, _('Older problems'), $old, $all, 0);
if ($q->{site} ne 'emptyhomes') {
- $col .= list_problems($q, _('Old problems, state unknown'), $open{$one_council}{unknown}, $all, 0);
+ $col .= list_problems($q, _('Old problems, state unknown'), $open{$id}{unknown}, $all, 0);
}
$vars{col_problems} = $col;
}
- if ($fixed{$one_council}) {
- my $col = list_problems($q, _('Recently fixed'), $fixed{$one_council}{new}, $all, 1);
- $col .= list_problems($q, _('Old fixed'), $fixed{$one_council}{old}, $all, 1);
+ if ($fixed{$id}) {
+ my $col = list_problems($q, _('Recently fixed'), $fixed{$id}{new}, $all, 1);
+ $col .= list_problems($q, _('Old fixed'), $fixed{$id}{old}, $all, 1);
$vars{col_fixed} = $col;
}
print Page::header($q, context => 'reports', title=>sprintf(_('%s - Summary reports'), $name), rss => [ sprintf(_('Problems within %s, FixMyStreet'), $name), Cobrand::url($cobrand, $rss_url, $q) ]);
@@ -291,8 +330,8 @@ sub list_problems {
$out .= '<li><a href="' . $url . '">';
$out .= ent($_->{title});
$out .= '</a>';
- $out .= ' <small>(sent to both)</small>' if $_->{councils}>1;
- $out .= ' <small>(not sent to council)</small>' if $_->{councils}==0 && $q->{site} ne 'emptyhomes';
+ $out .= ' <small>' . _('(sent to both)') . '</small>' if $_->{councils}>1;
+ $out .= ' <small>' . _('(not sent to council)') . '</small>' if $_->{councils}==0 && $q->{site} ne 'emptyhomes';
$out .= '<br><small>' . ent($_->{detail}) . '</small>' if $all;
$out .= '</li>';
}
diff --git a/web/rss.cgi b/web/rss.cgi
index 8885af249..1570ca97f 100755
--- a/web/rss.cgi
+++ b/web/rss.cgi
@@ -11,12 +11,14 @@
use strict;
use Error qw(:try);
use Standard;
+use Encode;
use URI::Escape;
use FixMyStreet::Alert;
use FixMyStreet::Geocode;
+use mySociety::Locale;
use mySociety::MaPit;
-use mySociety::GeoUtil;
use mySociety::Gaze;
+use Utils;
sub main {
my $q = shift;
@@ -62,6 +64,7 @@ Page::do_fastcgi(\&main);
sub rss_local_problems {
my $q = shift;
my $pc = $q->param('pc');
+
my $x = $q->param('x');
my $y = $q->param('y');
my $lat = $q->param('lat');
@@ -81,50 +84,86 @@ sub rss_local_problems {
$state = 'confirmed' if $state eq 'open';
+ my $qs;
+ my %title_params;
+ my $alert_type;
+
my $cobrand = Page::get_cobrand($q);
my $base = Cobrand::base_url($cobrand);
- if ($lat) { # In the UK, it'll never be 0 :)
- ($e, $n) = mySociety::GeoUtil::wgs84_to_national_grid($lat, $lon, 'G');
- $e = int($e + 0.5);
- $n = int($n + 0.5);
- print $q->redirect(-location => "$base/rss/n/$e,$n$d_str$state_qs");
- return '';
- } elsif ($x && $y) {
+ if ($x && $y) {
# 5000/31 as initial scale factor for these RSS feeds, now variable so redirect.
$e = int( ($x * 5000/31) + 0.5 );
$n = int( ($y * 5000/31) + 0.5 );
- print $q->redirect(-location => "$base/rss/n/$e,$n$d_str$state_qs");
+ ($lat, $lon) = Utils::convert_en_to_latlon_truncated($e, $n);
+ print $q->redirect(-location => "$base/rss/l/$lat,$lon$d_str$state_qs");
return '';
} elsif ($e && $n) {
- ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($e, $n, 'G');
+ ($lat, $lon) = Utils::convert_en_to_latlon_truncated($e, $n);
+ print $q->redirect(-location => "$base/rss/l/$lat,$lon$d_str$state_qs");
+ return '';
} elsif ($pc) {
my $error;
try {
- ($e, $n, $error) = FixMyStreet::Geocode::lookup($pc, $q);
+ ($lat, $lon, $error) = FixMyStreet::Geocode::lookup($pc, $q);
} catch Error::Simple with {
$error = shift;
};
- unless ($error) {
- print $q->redirect(-location => "$base/rss/n/$e,$n$d_str$state_qs");
+ if ($error) {
+ print $q->redirect(-location => "$base/alert");
+ return '';
+ } else {
+ ( $lat, $lon ) = map { Utils::truncate_coordinate($_) } ( $lat, $lon );
+
+ my $pretty_pc = $pc;
+ if (mySociety::PostcodeUtil::is_valid_postcode($pc)) {
+ $pretty_pc = mySociety::PostcodeUtil::canonicalise_postcode($pc);
+ }
+ my $pretty_pc_escaped = URI::Escape::uri_escape_utf8($pretty_pc);
+ $pretty_pc_escaped =~ s/%20/+/g;
+ $qs = "?pc=$pretty_pc_escaped";
+
+ $title_params{'POSTCODE'} = $pretty_pc;
}
- return '';
+ # pass through rather than redirecting.
+ } elsif ( $lat || $lon ) {
+ # pass through
} else {
die "Missing E/N, x/y, lat/lon, or postcode parameter in RSS feed";
}
- my $qs = '?e=' . int($e) . ';n=' . int($n);
+
+ # truncate the lat,lon for nicer urls
+ ( $lat, $lon ) = map { Utils::truncate_coordinate($_) } ( $lat, $lon );
+
+ if (!$qs) {
+ $qs = "?lat=$lat;lon=$lon";
+ }
+
if ($d) {
$qs .= ";d=$d";
$d = 100 if $d > 100;
} else {
$d = mySociety::Gaze::get_radius_containing_population($lat, $lon, 200000);
$d = int($d*10+0.5)/10;
+ mySociety::Locale::in_gb_locale {
+ $d = sprintf("%f", $d);
+ }
}
my $xsl = Cobrand::feed_xsl($cobrand);
- if ($state eq 'all') {
- return FixMyStreet::Alert::generate_rss('local_problems', $xsl, $qs, [$e, $n, $d], undef, $cobrand, $q);
+
+ if ($pc) {
+ $alert_type = 'postcode_local_problems';
} else {
- return FixMyStreet::Alert::generate_rss('local_problems_state', $xsl, $qs, [$e, $n, $d, $state], undef, $cobrand, $q);
+ $alert_type = 'local_problems';
+ }
+
+ my @db_params = ($lat, $lon, $d);
+
+ if ($state ne 'all') {
+ $alert_type .= '_state';
+ push @db_params, $state;
}
+
+ return FixMyStreet::Alert::generate_rss($alert_type, $xsl, $qs, \@db_params, \%title_params, $cobrand, $q);
}
diff --git a/web/tms-signup.cgi b/web/tms-signup.cgi
index 44099417f..5975a324f 100755
--- a/web/tms-signup.cgi
+++ b/web/tms-signup.cgi
@@ -108,7 +108,7 @@ sub tms_do_subscribe {
mobile => $input{mobile},
});
dbh()->commit();
- return Page::send_email($q, $input{email}, $input{name}, 'tms', %h);
+ return Page::send_confirmation_email($q, $input{email}, $input{name}, 'tms', %h);
}
sub tms_confirm {
diff --git a/web/xsl.eha.xsl b/web/xsl.eha.xsl
index 6c66037d7..14015cfd9 100644
--- a/web/xsl.eha.xsl
+++ b/web/xsl.eha.xsl
@@ -22,7 +22,7 @@
</ul>
</div>
- <div id="wrapper"><div id="content">
+ <div id="wrapper"><div id="mysociety">
<xsl:apply-templates select="rss/channel"/>
</div></div>
diff --git a/web/xsl.xsl b/web/xsl.xsl
index 9d30b1d61..1aa0eef4b 100644
--- a/web/xsl.xsl
+++ b/web/xsl.xsl
@@ -12,7 +12,7 @@
</head>
<body>
<div id="header"><a href="/">FixMyStreet</a></div>
- <div id="wrapper"><div id="content">
+ <div id="wrapper"><div id="mysociety">
<xsl:apply-templates select="rss/channel"/>
</div></div>