aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--db/schema.sql17
-rw-r--r--db/schema_0005-add_council_user_flag.sql6
-rw-r--r--db/schema_0006-alter_problem_state.sql19
-rw-r--r--db/schema_0007-add-comment-problem-state.sql16
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm10
-rw-r--r--perllib/FixMyStreet/App/Controller/Around.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/JSON.pm8
-rw-r--r--perllib/FixMyStreet/App/Controller/Photo.pm2
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Questionnaire.pm15
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm30
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm8
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm16
-rw-r--r--perllib/FixMyStreet/Cobrand/EmptyHomes.pm2
-rw-r--r--perllib/FixMyStreet/DB/Result/Comment.pm22
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm135
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm7
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/AlertType.pm6
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Nearby.pm2
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm10
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm2
-rw-r--r--perllib/FixMyStreet/Map/Tilma/Original.pm5
-rw-r--r--t/app/controller/admin.t2
-rw-r--r--t/app/controller/questionnaire.t9
-rw-r--r--t/app/controller/report_display.t73
-rw-r--r--t/app/controller/report_updates.t164
-rw-r--r--t/app/model/problem.t88
-rw-r--r--t/app/model/questionnaire.t106
-rw-r--r--t/map/tilma/original.t108
-rw-r--r--templates/web/default/admin/report_edit.html5
-rw-r--r--templates/web/default/report/display.html22
-rw-r--r--templates/web/default/report/updates.html1
-rw-r--r--web/css/core.css300
-rw-r--r--web/css/core.scss12
33 files changed, 998 insertions, 232 deletions
diff --git a/db/schema.sql b/db/schema.sql
index 9c5b3d8fd..21fc3371a 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -131,6 +131,7 @@ create table users (
name text,
phone text,
password text not null default ''
+ from_authority boolean not null default false -- users is from a council etc
);
-- Problems reported by users of site
@@ -165,7 +166,13 @@ create table problem (
state text not null check (
state = 'unconfirmed'
or state = 'confirmed'
+ or state = 'investigating'
+ or state = 'planned'
+ or state = 'in progress'
+ or state = 'closed'
or state = 'fixed'
+ or state = 'fixed - council'
+ or state = 'fixed - user'
or state = 'hidden'
or state = 'partial'
),
@@ -280,6 +287,16 @@ create table comment (
cobrand_data text not null default '' check (cobrand_data ~* '^[a-z0-9]*$'), -- Extra data used in cobranded versions of the site
mark_fixed boolean not null,
mark_open boolean not null default 'f'
+ problem_state text check (
+ problem_state = 'confirmed'
+ or problem_state = 'investigating'
+ or problem_state = 'planned'
+ or problem_state = 'in progress'
+ or problem_state = 'closed'
+ or problem_state = 'fixed'
+ or problem_state = 'fixed - council'
+ or problem_state = 'fixed - user'
+ )
-- other fields? one to indicate whether this was written by the council
-- and should be highlighted in the display?
);
diff --git a/db/schema_0005-add_council_user_flag.sql b/db/schema_0005-add_council_user_flag.sql
new file mode 100644
index 000000000..d8cf1358a
--- /dev/null
+++ b/db/schema_0005-add_council_user_flag.sql
@@ -0,0 +1,6 @@
+begin;
+
+ALTER table users
+ ADD COLUMN from_authority boolean NOT NULL DEFAULT false;
+
+commit;
diff --git a/db/schema_0006-alter_problem_state.sql b/db/schema_0006-alter_problem_state.sql
new file mode 100644
index 000000000..6fada1eb8
--- /dev/null
+++ b/db/schema_0006-alter_problem_state.sql
@@ -0,0 +1,19 @@
+begin;
+
+ ALTER TABLE problem DROP CONSTRAINT problem_state_check;
+
+ ALTER TABLE problem ADD CONSTRAINT problem_state_check CHECK (
+ state = 'unconfirmed'
+ or state = 'confirmed'
+ or state = 'investigating'
+ or state = 'planned'
+ or state = 'in progress'
+ or state = 'closed'
+ or state = 'fixed'
+ or state = 'fixed - council'
+ or state = 'fixed - user'
+ or state = 'hidden'
+ or state = 'partial'
+ );
+
+commit;
diff --git a/db/schema_0007-add-comment-problem-state.sql b/db/schema_0007-add-comment-problem-state.sql
new file mode 100644
index 000000000..8fa361d83
--- /dev/null
+++ b/db/schema_0007-add-comment-problem-state.sql
@@ -0,0 +1,16 @@
+begin;
+
+ ALTER TABLE comment ADD column problem_state text;
+
+ ALTER TABLE comment ADD CONSTRAINT problem_state_check CHECK (
+ problem_state = 'confirmed'
+ or problem_state = 'investigating'
+ or problem_state = 'planned'
+ or problem_state = 'in progress'
+ or problem_state = 'closed'
+ or problem_state = 'fixed'
+ or problem_state = 'fixed - council'
+ or problem_state = 'fixed - user'
+ );
+
+commit;
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index abc454600..ae4154e98 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -56,10 +56,12 @@ sub index : Path : Args(0) {
%prob_counts =
map { $_ => $prob_counts{$_} || 0 }
- qw(confirmed fixed unconfirmed hidden partial);
+ ('confirmed', 'investigating', 'in progress', 'closed', 'fixed - council',
+ 'fixed - user', 'fixed', 'unconfirmed', 'hidden',
+ 'partial', 'planned');
$c->stash->{problems} = \%prob_counts;
- $c->stash->{total_problems_live} =
- $prob_counts{confirmed} + $prob_counts{fixed};
+ $c->stash->{total_problems_live} += $prob_counts{$_}
+ for ( FixMyStreet::DB::Result::Problem->visible_states() );
my $comments = $c->model('DB::Comment')->summary_count( $site_restriction );
@@ -740,7 +742,7 @@ sub update_edit : Path('update_edit') : Args(1) {
# If we're hiding an update, see if it marked as fixed and unfix if so
if ( $new_state eq 'hidden' && $update->mark_fixed ) {
- if ( $update->problem->state eq 'fixed' ) {
+ if ( $update->problem->is_fixed ) {
$update->problem->state('confirmed');
$update->problem->update;
}
diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm
index a49d796fc..ec1fde4e4 100644
--- a/perllib/FixMyStreet/App/Controller/Around.pm
+++ b/perllib/FixMyStreet/App/Controller/Around.pm
@@ -189,7 +189,7 @@ sub display_location : Private {
{
latitude => $p->latitude,
longitude => $p->longitude,
- colour => $p->state eq 'fixed' ? 'green' : 'red',
+ colour => $p->is_fixed ? 'green' : 'red',
id => $p->id,
title => $p->title,
}
diff --git a/perllib/FixMyStreet/App/Controller/JSON.pm b/perllib/FixMyStreet/App/Controller/JSON.pm
index 3a3010911..d9baeaaf8 100644
--- a/perllib/FixMyStreet/App/Controller/JSON.pm
+++ b/perllib/FixMyStreet/App/Controller/JSON.pm
@@ -70,12 +70,12 @@ sub problems : Local {
}
# query the database
- my ( $state, $date_col );
+ my ( @state, $date_col );
if ( $type eq 'new_problems' ) {
- $state = 'confirmed';
+ @state = FixMyStreet::DB::Result::Problem->open_states();
$date_col = 'created';
} elsif ( $type eq 'fixed_problems' ) {
- $state = 'fixed';
+ @state = FixMyStreet::DB::Result::Problem->fixed_states();
$date_col = 'lastupdate';
}
@@ -85,7 +85,7 @@ sub problems : Local {
'>=' => $start_dt,
'<=' => $end_dt + $one_day,
},
- state => $state,
+ state => [ @state ],
}, {
order_by => { -asc => 'confirmed' },
columns => [
diff --git a/perllib/FixMyStreet/App/Controller/Photo.pm b/perllib/FixMyStreet/App/Controller/Photo.pm
index 17862aa0a..b4fa3a457 100644
--- a/perllib/FixMyStreet/App/Controller/Photo.pm
+++ b/perllib/FixMyStreet/App/Controller/Photo.pm
@@ -48,7 +48,7 @@ sub index :Path :Args(0) {
$c->detach( 'no_photo' ) if $id =~ /\D/;
@photo = $c->cobrand->problems->search( {
id => $id,
- state => [ 'confirmed', 'fixed', 'partial' ],
+ state => [ FixMyStreet::DB::Result::Problem->visible_states(), 'partial' ],
photo => { '!=', undef },
} );
}
diff --git a/perllib/FixMyStreet/App/Controller/Questionnaire.pm b/perllib/FixMyStreet/App/Controller/Questionnaire.pm
index 19d057958..ad3827de9 100755
--- a/perllib/FixMyStreet/App/Controller/Questionnaire.pm
+++ b/perllib/FixMyStreet/App/Controller/Questionnaire.pm
@@ -48,7 +48,7 @@ sub load_questionnaire : Private {
$c->detach;
}
- unless ( $questionnaire->problem->state eq 'confirmed' || $questionnaire->problem->state eq 'fixed' ) {
+ unless ( $questionnaire->problem->is_visible ) {
$c->detach('missing_problem');
}
@@ -128,8 +128,8 @@ sub submit_creator_fixed : Private {
my $questionnaire = $c->model( 'DB::Questionnaire' )->find_or_new(
{
problem_id => $c->stash->{problem},
- old_state => 'confirmed',
- new_state => 'fixed',
+ old_state => [ FixMyStreet::DB::Result::Problem->open_states() ],
+ new_state => 'fixed - user',
}
);
@@ -156,8 +156,10 @@ sub submit_standard : Private {
my $problem = $c->stash->{problem};
my $old_state = $problem->state;
my $new_state = '';
- $new_state = 'fixed' if $c->stash->{been_fixed} eq 'Yes' && $old_state eq 'confirmed';
- $new_state = 'confirmed' if $c->stash->{been_fixed} eq 'No' && $old_state eq 'fixed';
+ $new_state = 'fixed - user' if $c->stash->{been_fixed} eq 'Yes' &&
+ FixMyStreet::DB::Result::Problem->open_states()->{$old_state};
+ $new_state = 'confirmed' if $c->stash->{been_fixed} eq 'No' &&
+ FixMyStreet::DB::Result::Problem->fixed_states()->{$old_state};
# Record state change, if there was one
if ( $new_state ) {
@@ -166,7 +168,8 @@ sub submit_standard : Private {
}
# If it's not fixed and they say it's still not been fixed, record time update
- if ( $c->stash->{been_fixed} eq 'No' && $old_state eq 'confirmed' ) {
+ if ( $c->stash->{been_fixed} eq 'No' &&
+ FixMyStreet::DB::Result::Problem->open_states($old_state) ) {
$problem->lastupdate( \'ms_current_timestamp()' );
}
diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm
index d586035bc..2d810d871 100644
--- a/perllib/FixMyStreet/App/Controller/Report/Update.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm
@@ -52,7 +52,7 @@ sub update_problem : Private {
my $problem = $c->stash->{problem} || $update->problem;
if ( $update->mark_fixed ) {
- $problem->state('fixed');
+ $problem->state('fixed - user');
if ( $update->user->id == $problem->user->id ) {
$problem->send_questionnaire(0);
@@ -65,6 +65,10 @@ sub update_problem : Private {
}
}
+ if ( $update->problem_state ) {
+ $problem->state( $update->problem_state );
+ }
+
$problem->lastupdate( \'ms_current_timestamp()' );
$problem->update;
@@ -122,7 +126,7 @@ sub process_update : Private {
my ( $self, $c ) = @_;
my %params =
- map { $_ => scalar $c->req->param($_) } ( 'update', 'name', 'fixed' );
+ map { $_ => scalar $c->req->param($_) } ( 'update', 'name', 'fixed', 'state' );
$params{update} =
Utils::cleanup_text( $params{update}, { allow_multiline => 1 } );
@@ -147,6 +151,12 @@ sub process_update : Private {
}
);
+ if ( $params{state} ) {
+ $params{state} = 'fixed - council'
+ if $params{state} eq 'fixed' && $c->user && $c->user->from_authority;
+ $update->problem_state( $params{state} );
+ }
+
$c->stash->{update} = $update;
$c->stash->{add_alert} = $c->req->param('add_alert');
@@ -164,6 +174,22 @@ return false.
sub check_for_errors : Private {
my ( $self, $c ) = @_;
+ # they have to be an authority user to update the state
+ if ( $c->req->param('state') ) {
+ my $error = 0;
+ $error = 1 unless $c->user && $c->user->from_authority;
+
+ my $state = $c->req->param('state');
+ $error = 1 unless ( grep { $state eq $_ } ( qw/closed fixed investigating planned/, 'in progress', 'fixed', 'fixed - user', 'fixed - council' ) );
+
+ if ( $error ) {
+ $c->stash->{errors} ||= [];
+ push @{ $c->stash->{errors} }, _('There was a problem with your update. Please try again.');
+ return;
+ }
+
+ }
+
# let the model check for errors
my %field_errors = (
%{ $c->stash->{update}->user->check_for_errors },
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index a3aeb8505..fc8c4cd0e 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -259,7 +259,7 @@ sub load_and_group_problems : Private {
my ( $self, $c ) = @_;
my $where = {
- state => [ 'confirmed', 'fixed' ]
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ]
};
my @extra_cols = ();
if ($c->stash->{ward}) {
@@ -354,9 +354,11 @@ sub add_row {
? 'unknown'
: ($problem->{age} > $fourweeks ? 'older' : 'new');
# Fixed problems are either old or new
- push @{$fixed->{$council}{$duration_str}}, $problem if $problem->{state} eq 'fixed';
+ push @{$fixed->{$council}{$duration_str}}, $problem if
+ exists FixMyStreet::DB::Result::Problem->fixed_states()->{$problem->{state}};
# Open problems are either unknown, older, or new
- push @{$open->{$council}{$type}}, $problem if $problem->{state} eq 'confirmed';
+ push @{$open->{$council}{$type}}, $problem if
+ exists FixMyStreet::DB::Result::Problem->open_states->{$problem->{state}};
}
=head1 AUTHOR
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 864415b4c..878e98c10 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -822,14 +822,24 @@ sub generate_problem_banner {
my ( $self, $problem ) = @_;
my $banner = {};
- if ($problem->state eq 'confirmed' && time() - $problem->lastupdate_local->epoch > 8*7*24*60*60) {
- $banner->{id} = 'unknown';
+ if ( $problem->is_open && time() - $problem->lastupdate_local->epoch > 8 * 7 * 24 * 60 * 60 )
+ {
+ $banner->{id} = 'unknown';
$banner->{text} = _('This problem is old and of unknown status.');
}
- if ($problem->state eq 'fixed') {
+ if ($problem->is_fixed) {
$banner->{id} = 'fixed';
$banner->{text} = _('This problem has been fixed') . '.';
}
+ if ($problem->is_closed) {
+ $banner->{id} = 'closed';
+ $banner->{text} = _('This problem has been closed') . '.';
+ }
+
+ if ( grep { $problem->state eq $_ } ( 'investigating', 'in progress', 'planned' ) ) {
+ $banner->{id} = 'progress';
+ $banner->{text} = _('This problem is in progress') . '.';
+ }
return $banner;
}
diff --git a/perllib/FixMyStreet/Cobrand/EmptyHomes.pm b/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
index 4a93bcb20..3694d984b 100644
--- a/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
+++ b/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
@@ -112,7 +112,7 @@ sub generate_problem_banner {
my ( $self, $problem ) = @_;
my $banner = {};
- if ($problem->state eq 'fixed') {
+ if ($problem->is_fixed ) {
$banner->{id} = 'fixed';
$banner->{text} = _('This problem has been fixed') . '.';
}
diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm
index 18bcedc1b..9ed9d8b48 100644
--- a/perllib/FixMyStreet/DB/Result/Comment.pm
+++ b/perllib/FixMyStreet/DB/Result/Comment.pm
@@ -52,6 +52,8 @@ __PACKAGE__->add_columns(
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"anonymous",
{ data_type => "boolean", is_nullable => 0 },
+ "problem_state",
+ { data_type => "text", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
@@ -68,8 +70,8 @@ __PACKAGE__->belongs_to(
);
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-06-23 15:49:48
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:TYFusbxkOkAewaiZYZVJUA
+# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-06-23 14:25:34
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:scnPU5RAGLnT0fY1gM6Z5A
use DateTime::TimeZone;
use Image::Size;
@@ -144,6 +146,22 @@ sub get_photo_params {
return $photo;
}
+=head2 meta_problem_state
+
+Returns a string suitable for display in the update meta section.
+Mostly removes the '- council/user' bit from fixed states
+
+=cut
+
+sub meta_problem_state {
+ my $self = shift;
+
+ my $state = $self->problem_state;
+ $state =~ s/ -.*$//;
+
+ return $state;
+}
+
# we need the inline_constructor bit as we don't inherit from Moose
__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index c5851b256..1c8487ae7 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -119,6 +119,92 @@ use Utils;
with 'FixMyStreet::Roles::Abuser';
+=head2
+
+ @states = FixMyStreet::DB::Problem::open_states();
+
+Get a list or states that are regarded as open. If called in
+array context then returns an array of names, otherwise returns a
+HASHREF.
+
+=cut
+
+sub open_states {
+ my $states = {
+ 'confirmed' => 1,
+ 'investigating' => 1,
+ 'planned' => 1,
+ 'in progress' => 1,
+ };
+
+ return wantarray ? keys %{$states} : $states;
+}
+
+=head2
+
+ @states = FixMyStreet::DB::Problem::fixed_states();
+
+Get a list or states that should be regarded as fixed. If called in
+array context then returns an array of names, otherwise returns a
+HASHREF.
+
+=cut
+
+sub fixed_states {
+ my $states = {
+ 'fixed' => 1,
+ 'fixed - user' => 1,
+ 'fixed - council' => 1,
+ };
+
+ return wantarray ? keys %{ $states } : $states;
+}
+
+=head2
+
+ @states = FixMyStreet::DB::Problem::closed_states();
+
+Get a list or states that should be regarded as closed. If called in
+array context then returns an array of names, otherwise returns a
+HASHREF.
+
+=cut
+
+sub closed_states {
+ my $states = {
+ 'closed' => 1,
+ };
+
+ return wantarray ? keys %{$states} : $states;
+}
+
+
+=head2
+
+ @states = FixMyStreet::DB::Problem::visible_states();
+
+Get a list or states that should be visible on the site. If called in
+array context then returns an array of names, otherwise returns a
+HASHREF.
+
+=cut
+
+sub visible_states {
+ my $states = {
+ 'confirmed' => 1,
+ 'planned' => 1,
+ 'investigating' => 1,
+ 'in progress' => 1,
+ 'fixed' => 1,
+ 'fixed - council' => 1,
+ 'fixed - user' => 1,
+ 'closed' => 1,
+ };
+
+ return wantarray ? keys %{$states} : $states;
+}
+
+
my $tz = DateTime::TimeZone->new( name => "local" );
sub confirmed_local {
@@ -284,6 +370,55 @@ sub get_photo_params {
return $photo;
}
+=head2 is_open
+
+Returns 1 if the problem is in a open state otherwise 0.
+
+=cut
+
+sub is_open {
+ my $self = shift;
+
+ return exists $self->open_states->{ $self->state } ? 1 : 0;
+}
+
+
+=head2 is_fixed
+
+Returns 1 if the problem is in a fixed state otherwise 0.
+
+=cut
+
+sub is_fixed {
+ my $self = shift;
+
+ return exists $self->fixed_states->{ $self->state } ? 1 : 0;
+}
+
+=head2 is_closed
+
+Returns 1 if the problem is in a closed state otherwise 0.
+
+=cut
+
+sub is_closed {
+ my $self = shift;
+
+ return exists $self->closed_states->{ $self->state } ? 1 : 0;
+}
+
+=head2 is_visible
+
+Returns 1 if the problem should be displayed on the site otherwise 0.
+
+=cut
+
+sub is_visible {
+ my $self = shift;
+
+ return exists $self->visible_states->{ $self->state } ? 1 : 0;
+}
+
=head2 meta_line
Returns a string to be used on a problem report page, describing some of the
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index 95e9908c3..c0b078775 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -26,6 +26,8 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 1 },
"password",
{ data_type => "text", default_value => "", is_nullable => 0 },
+ "from_authority",
+ { data_type => "boolean", default_value => \"false", is_nullable => 0 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("users_email_key", ["email"]);
@@ -49,8 +51,8 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-06-23 15:49:48
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:T2JK+KyfoE2hkCLgreq1XQ
+# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-06-22 16:10:43
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zQIniwAXjl5Lh9wyiGuwFw
__PACKAGE__->add_columns(
"password" => {
@@ -60,6 +62,7 @@ __PACKAGE__->add_columns(
encode_check_method => 'check_password',
},
);
+>>>>>>> 62ffebc89cc66d32a828ea1de8c850c3e950faa1
use mySociety::EmailUtil;
diff --git a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
index e92846aca..d5b2f5535 100644
--- a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
@@ -74,7 +74,8 @@ sub email_alerts ($) {
# create problem status message for the templates
$data{state_message} =
- $row->{state} eq 'fixed'
+ # XXXXXX test this
+ FixMyStreet::DB::Result::Problem::fixed_states()->{$row->{state}}
? _("This report is currently marked as fixed.")
: _("This report is currently marked as open.");
@@ -129,11 +130,12 @@ sub email_alerts ($) {
$d = mySociety::Locale::in_gb_locale {
sprintf("%f", int($d*10+0.5)/10);
};
+ my $states = "'" . join( "', '", FixMyStreet::DB::Result::Problem::visible_states() ) . "'";
my %data = ( template => $template, data => '', alert_id => $alert->id, alert_email => $alert->user->email, lang => $alert->lang, cobrand => $alert->cobrand, cobrand_data => $alert->cobrand_data );
my $q = "select problem.id, problem.title from problem_find_nearby(?, ?, ?) as nearby, problem, users
where nearby.problem_id = problem.id
and problem.user_id = users.id
- and problem.state in ('confirmed', 'fixed')
+ and problem.state in ($states)
and problem.confirmed >= ? and problem.confirmed >= ms_current_timestamp() - '7 days'::interval
and (select whenqueued from alert_sent where alert_sent.alert_id = ? and alert_sent.parameter::integer = problem.id) is null
and users.email <> ?
diff --git a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
index 3b3a3d90b..04089096e 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
@@ -8,7 +8,7 @@ sub nearby {
my ( $rs, $c, $dist, $ids, $limit, $mid_lat, $mid_lon, $interval ) = @_;
my $params = {
- state => [ 'confirmed', 'fixed' ],
+ state => [ FixMyStreet::DB::Result::Problem::visible_states() ],
};
$params->{'current_timestamp-lastupdate'} = { '<', \"'$interval'::interval" }
if $interval;
diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
index b1b1e00a4..4de8f2e5f 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
@@ -21,7 +21,7 @@ sub recent_fixed {
my $result = Memcached::get($key);
unless ($result) {
$result = $rs->search( {
- state => 'fixed',
+ state => [ FixMyStreet::DB::Result::Problem->fixed_states() ],
lastupdate => { '>', \"current_timestamp-'1 month'::interval" },
} )->count;
Memcached::set($key, $result, 3600);
@@ -50,7 +50,7 @@ sub recent_new {
my $result = Memcached::get($key);
unless ($result) {
$result = $rs->search( {
- state => [ 'confirmed', 'fixed' ],
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ],
confirmed => { '>', \"current_timestamp-'$interval'::interval" },
} )->count;
Memcached::set($key, $result, 3600);
@@ -66,7 +66,7 @@ sub recent {
my $result = Memcached::get($key);
unless ($result) {
$result = [ $rs->search( {
- state => [ 'confirmed', 'fixed' ]
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ]
}, {
columns => [ 'id', 'title' ],
order_by => { -desc => 'confirmed' },
@@ -81,7 +81,7 @@ sub recent_photos {
my ( $rs, $num, $lat, $lon, $dist ) = @_;
my $probs;
my $query = {
- state => [ 'confirmed', 'fixed' ],
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ],
photo => { '!=', undef },
};
my $attrs = {
@@ -125,7 +125,7 @@ sub around_map {
$attr->{rows} = $limit if $limit;
my $q = {
- state => [ 'confirmed', 'fixed' ],
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ],
latitude => { '>=', $min_lat, '<', $max_lat },
longitude => { '>=', $min_lon, '<', $max_lon },
};
diff --git a/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm b/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm
index e490c77a6..665e0e3e0 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm
@@ -19,7 +19,7 @@ sub send_questionnaires_period {
# Select all problems that need a questionnaire email sending
my $q_params = {
- state => [ 'confirmed', 'fixed' ],
+ state => [ FixMyStreet::DB::Result::Problem::visible_states() ],
whensent => [
'-and',
{ '!=', undef },
diff --git a/perllib/FixMyStreet/Map/Tilma/Original.pm b/perllib/FixMyStreet/Map/Tilma/Original.pm
index 6fa854cb2..8fd835265 100644
--- a/perllib/FixMyStreet/Map/Tilma/Original.pm
+++ b/perllib/FixMyStreet/Map/Tilma/Original.pm
@@ -102,6 +102,7 @@ sub map_pins {
my $n = tile_to_os($y);
my ( $lat, $lon ) = Utils::convert_en_to_latlon( $e, $n );
+
my ( $around_map, $around_map_list, $nearby, $dist ) =
FixMyStreet::Map::map_features( $c, $lat, $lon, $interval );
@@ -111,7 +112,7 @@ sub map_pins {
_ll_to_en( $_->latitude, $_->longitude );
my $px = os_to_px($easting, $sx);
my $py = os_to_px($northing, $sy, 1);
- my $col = $_->state eq 'fixed' ? 'green' : 'red';
+ my $col = exists FixMyStreet::DB::Result::Problem->fixed_states()->{$_->state} ? 'green' : 'red';
$pins .= display_pin($c, $px, $py, $col, $_->id, $_->title);
}
@@ -121,7 +122,7 @@ sub map_pins {
_ll_to_en( $p->latitude, $p->longitude );
my $px = os_to_px($easting, $sx);
my $py = os_to_px($northing, $sy, 1);
- my $col = $p->state eq 'fixed' ? 'green' : 'red';
+ my $col = exists FixMyStreet::DB::Result::Problem->fixed_states()->{$p->state} ? 'green' : 'red';
$pins .= display_pin($c, $px, $py, $col, $p->id, $p->title);
}
diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t
index ba5095cea..51c55c323 100644
--- a/t/app/controller/admin.t
+++ b/t/app/controller/admin.t
@@ -77,7 +77,7 @@ my $alert = FixMyStreet::App->model('DB::Alert')->find_or_create(
);
subtest 'check summary counts' => sub {
- my $problems = FixMyStreet::App->model('DB::Problem')->search( { state => { -in => [qw/confirmed fixed/] } } );
+ my $problems = FixMyStreet::App->model('DB::Problem')->search( { state => { -in => [qw/confirmed fixed closed investigating planned/, 'in progress', 'fixed - user', 'fixed - council'] } } );
my $problem_count = $problems->count;
$problems->update( { cobrand => '' } );
diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t
index e56734bfc..af99a058e 100644
--- a/t/app/controller/questionnaire.t
+++ b/t/app/controller/questionnaire.t
@@ -204,7 +204,12 @@ foreach my $test (
}
my $result;
- $result = 'fixed' if $test->{fields}{been_fixed} eq 'Yes';
+ $result = 'fixed - user'
+ if $test->{fields}{been_fixed} eq 'Yes'
+ && $test->{problem_state} ne 'fixed';
+ $result = 'fixed'
+ if $test->{fields}{been_fixed} eq 'Yes'
+ && $test->{problem_state} eq 'fixed';
$result = 'confirmed' if $test->{fields}{been_fixed} eq 'No';
$result = 'unknown' if $test->{fields}{been_fixed} eq 'Unknown';
@@ -214,7 +219,7 @@ foreach my $test (
# Check the right HTML page has been returned
$mech->content_like( qr/<title>[^<]*Questionnaire/m );
$mech->content_contains( 'glad to hear it&rsquo;s been fixed' )
- if $result eq 'fixed';
+ if $result =~ /fixed/;
$mech->content_contains( 'get some more information about the status of your problem' )
if $result eq 'unknown';
$mech->content_contains( "sorry to hear that" )
diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t
index 1f857a387..fc844e31c 100644
--- a/t/app/controller/report_display.t
+++ b/t/app/controller/report_display.t
@@ -235,6 +235,54 @@ for my $test (
banner_text => 'This problem has been fixed.',
fixed => 1
},
+ {
+ description => 'user fixed report',
+ date => DateTime->now,
+ state => 'fixed - user',
+ banner_id => 'fixed',
+ banner_text => 'This problem has been fixed.',
+ fixed => 1
+ },
+ {
+ description => 'council fixed report',
+ date => DateTime->now,
+ state => 'fixed - council',
+ banner_id => 'fixed',
+ banner_text => 'This problem has been fixed.',
+ fixed => 1
+ },
+ {
+ description => 'closed report',
+ date => DateTime->now,
+ state => 'closed',
+ banner_id => 'closed',
+ banner_text => 'This problem has been closed.',
+ fixed => 0
+ },
+ {
+ description => 'investigating report',
+ date => DateTime->now,
+ state => 'investigating',
+ banner_id => 'progress',
+ banner_text => 'This problem is in progress.',
+ fixed => 0
+ },
+ {
+ description => 'planned report',
+ date => DateTime->now,
+ state => 'planned',
+ banner_id => 'progress',
+ banner_text => 'This problem is in progress.',
+ fixed => 0
+ },
+ {
+ description => 'in progressreport',
+ date => DateTime->now,
+ state => 'in progress',
+ banner_id => 'progress',
+ banner_text => 'This problem is in progress.',
+ fixed => 0
+ },
) {
subtest "banner for $test->{description}" => sub {
$report->confirmed( $test->{date}->ymd . ' ' . $test->{date}->hms );
@@ -260,6 +308,31 @@ for my $test (
};
}
+for my $test (
+ {
+ desc => 'no state dropdown if user not from authority',
+ from_authority => 0,
+ },
+ {
+ desc => 'state dropdown if user from authority',
+ from_authority => 1,
+ },
+) {
+ subtest $test->{desc} => sub {
+ $mech->log_in_ok( $user->email );
+ $user->from_authority( $test->{from_authority} );
+ $user->update;
+
+ $mech->get_ok("/report/$report_id");
+ my $fields = $mech->visible_form_values( 'updateForm' );
+ if ( $test->{from_authority} ) {
+ ok $fields->{state};
+ } else {
+ ok !$fields->{state};
+ }
+ };
+}
+
# tidy up
$mech->delete_user('test@example.com');
done_testing();
diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t
index fb2f7abb7..f0916610b 100644
--- a/t/app/controller/report_updates.t
+++ b/t/app/controller/report_updates.t
@@ -382,6 +382,170 @@ for my $test (
};
}
+$report->state('confirmed');
+$report->update;
+
+subtest 'check non authority user cannot change set state' => sub {
+ $mech->log_in_ok( $user->email );
+ $user->from_authority( 0 );
+ $user->update;
+
+ $mech->get_ok("/report/$report_id");
+ $mech->submit_form_ok( {
+ form_number => 2,
+ fields => {
+ submit_update => 1,
+ id => $report_id,
+ name => $user->name,
+ rznvy => $user->email,
+ may_show_name => 1,
+ add_alert => 0,
+ photo => '',
+ update => 'this is a forbidden update',
+ state => 'fixed - council',
+ },
+ },
+ 'submitted with state',
+ );
+
+ is $mech->uri->path, "/report/update", "at /report/update";
+
+ my $errors = $mech->page_errors;
+ is_deeply $errors, [ 'There was a problem with your update. Please try again.' ], 'error message';
+
+ is $report->state, 'confirmed', 'state unchanged';
+};
+
+for my $state ( qw/unconfirmed hidden partial/ ) {
+ subtest "check that update cannot set state to $state" => sub {
+ $mech->log_in_ok( $user->email );
+ $user->from_authority( 1 );
+ $user->update;
+
+ $mech->get_ok("/report/$report_id");
+ $mech->submit_form_ok( {
+ form_number => 2,
+ fields => {
+ submit_update => 1,
+ id => $report_id,
+ name => $user->name,
+ rznvy => $user->email,
+ may_show_name => 1,
+ add_alert => 0,
+ photo => '',
+ update => 'this is a forbidden update',
+ state => $state,
+ },
+ },
+ 'submitted with state',
+ );
+
+ is $mech->uri->path, "/report/update", "at /report/update";
+
+ my $errors = $mech->page_errors;
+ is_deeply $errors, [ 'There was a problem with your update. Please try again.' ], 'error message';
+
+ is $report->state, 'confirmed', 'state unchanged';
+ };
+}
+
+for my $test (
+ {
+ desc => 'from authority user marks report as investigating',
+ fields => {
+ name => $user->name,
+ may_show_name => 1,
+ add_alert => 0,
+ photo => '',
+ update => 'Set state to investigating',
+ state => 'investigating',
+ },
+ state => 'investigating',
+ },
+ {
+ desc => 'from authority user marks report as planned',
+ fields => {
+ name => $user->name,
+ may_show_name => 1,
+ add_alert => 0,
+ photo => '',
+ update => 'Set state to planned',
+ state => 'planned',
+ },
+ state => 'planned',
+ },
+ {
+ desc => 'from authority user marks report as in progress',
+ fields => {
+ name => $user->name,
+ may_show_name => 1,
+ add_alert => 0,
+ photo => '',
+ update => 'Set state to in progress',
+ state => 'in progress',
+ },
+ state => 'in progress',
+ },
+ {
+ desc => 'from authority user marks report as closed',
+ fields => {
+ name => $user->name,
+ may_show_name => 1,
+ add_alert => 0,
+ photo => '',
+ update => 'Set state to closed',
+ state => 'closed',
+ },
+ state => 'closed',
+ },
+ {
+ desc => 'from authority user marks report as fixed',
+ fields => {
+ name => $user->name,
+ may_show_name => 1,
+ add_alert => 0,
+ photo => '',
+ update => 'Set state to fixed',
+ state => 'fixed',
+ },
+ state => 'fixed - council',
+ },
+) {
+ subtest $test->{desc} => sub {
+ $report->comments->delete;
+
+ $mech->log_in_ok( $user->email );
+ $user->from_authority( 1 );
+ $user->update;
+
+ $mech->get_ok("/report/$report_id");
+
+ $mech->submit_form_ok(
+ {
+ with_fields => $test->{fields},
+ },
+ 'submit update'
+ );
+
+ my $update = $report->comments->first;
+ ok $update, 'found update';
+ is $update->text, $test->{fields}->{update}, 'update text';
+ is $update->problem_state, $test->{state}, 'problem state set';
+
+ my $update_meta = $mech->extract_update_metas;
+ like $update_meta->[0], qr/marked as $test->{fields}->{state}$/, 'update meta includes state change';
+
+ $report->discard_changes;
+ is $report->state, $test->{state}, 'state set';
+ };
+}
+
+$user->from_authority(0);
+$user->update;
+
+$report->state('confirmed');
+$report->update;
+
for my $test (
{
desc => 'submit update for registered user',
diff --git a/t/app/model/problem.t b/t/app/model/problem.t
index 1b8804fce..4c6be6a8d 100644
--- a/t/app/model/problem.t
+++ b/t/app/model/problem.t
@@ -152,4 +152,92 @@ for my $test (
};
}
+for my $test (
+ {
+ state => 'partial',
+ is_visible => 0,
+ is_fixed => 0,
+ is_open => 0,
+ is_closed => 0,
+ },
+ {
+ state => 'hidden',
+ is_visible => 0,
+ is_fixed => 0,
+ is_open => 0,
+ is_closed => 0,
+ },
+ {
+ state => 'unconfirmed',
+ is_visible => 0,
+ is_fixed => 0,
+ is_open => 0,
+ is_closed => 0,
+ },
+ {
+ state => 'confirmed',
+ is_visible => 1,
+ is_fixed => 0,
+ is_open => 1,
+ is_closed => 0,
+ },
+ {
+ state => 'investigating',
+ is_visible => 1,
+ is_fixed => 0,
+ is_open => 1,
+ is_closed => 0,
+ },
+ {
+ state => 'planned',
+ is_visible => 1,
+ is_fixed => 0,
+ is_open => 1,
+ is_closed => 0,
+ },
+ {
+ state => 'in progress',
+ is_visible => 1,
+ is_fixed => 0,
+ is_open => 1,
+ is_closed => 0,
+ },
+ {
+ state => 'fixed',
+ is_visible => 1,
+ is_fixed => 1,
+ is_open => 0,
+ is_closed => 0,
+ },
+ {
+ state => 'fixed - council',
+ is_visible => 1,
+ is_fixed => 1,
+ is_open => 0,
+ is_closed => 0,
+ },
+ {
+ state => 'fixed - user',
+ is_visible => 1,
+ is_fixed => 1,
+ is_open => 0,
+ is_closed => 0,
+ },
+ {
+ state => 'closed',
+ is_visible => 1,
+ is_fixed => 0,
+ is_open => 0,
+ is_closed => 1,
+ },
+) {
+ subtest $test->{state} . ' is fixed/open/closed/visible' => sub {
+ $problem->state( $test->{state} );
+ is $problem->is_visible, $test->{is_visible}, 'is_visible';
+ is $problem->is_fixed, $test->{is_fixed}, 'is_fixed';
+ is $problem->is_closed, $test->{is_closed}, 'is_closed';
+ is $problem->is_open, $test->{is_open}, 'is_open';
+ };
+}
+
done_testing();
diff --git a/t/app/model/questionnaire.t b/t/app/model/questionnaire.t
new file mode 100644
index 000000000..60b52043a
--- /dev/null
+++ b/t/app/model/questionnaire.t
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+
+use FixMyStreet;
+use FixMyStreet::TestMech;
+
+my $user = FixMyStreet::App->model('DB::User')->find_or_create( { email => 'test@example.com' } );
+
+my $problem = FixMyStreet::App->model('DB::Problem')->create(
+ {
+ postcode => 'EH99 1SP',
+ latitude => 1,
+ longitude => 1,
+ areas => 1,
+ title => 'to be sent',
+ detail => 'detail',
+ used_map => 1,
+ user_id => 1,
+ name => 'A Name',
+ state => 'confirmed',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ confirmed => \"ms_current_timestamp() - '5 weeks'::interval",
+ whensent => \"ms_current_timestamp() - '5 weeks'::interval",
+ user => $user,
+ anonymous => 0,
+ }
+);
+
+diag $problem->id;
+
+my $mech = FixMyStreet::TestMech->new;
+
+for my $test (
+ {
+ state => 'unconfirmed',
+ send_email => 0,
+ },
+ {
+ state => 'partial',
+ send_email => 0,
+ },
+ {
+ state => 'hidden',
+ send_email => 0,
+ },
+ {
+ state => 'confirmed',
+ send_email => 1,
+ },
+ {
+ state => 'investigating',
+ send_email => 1,
+ },
+ {
+ state => 'planned',
+ send_email => 1,
+ },
+ {
+ state => 'in progress',
+ send_email => 1,
+ },
+ {
+ state => 'fixed',
+ send_email => 1,
+ },
+ {
+ state => 'fixed - council',
+ send_email => 1,
+ },
+ {
+ state => 'fixed - user',
+ send_email => 1,
+ },
+ {
+ state => 'closed',
+ send_email => 1,
+ },
+) {
+ subtest "correct questionnaire behviour for state $test->{state}" => sub {
+ $problem->discard_changes;
+ $problem->state( $test->{state} );
+ $problem->send_questionnaire( 1 );
+ $problem->update;
+
+ $problem->questionnaires->delete;
+
+ $mech->email_count_is(0);
+
+ FixMyStreet::App->model('DB::Questionnaire')
+ ->send_questionnaires( { site => 'fixmystreet' } );
+
+ $mech->email_count_is( $test->{send_email} );
+
+ $mech->clear_emails_ok();
+ }
+}
+
+$mech->delete_user( $user );
+
+done_testing();
diff --git a/t/map/tilma/original.t b/t/map/tilma/original.t
new file mode 100644
index 000000000..b953a32b2
--- /dev/null
+++ b/t/map/tilma/original.t
@@ -0,0 +1,108 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Test::More;
+use FixMyStreet::App;
+use FixMyStreet::Map;
+use FixMyStreet::TestMech;
+use DateTime;
+use mySociety::Locale;
+
+my $mech = FixMyStreet::TestMech->new;
+
+mySociety::Locale::gettext_domain('FixMyStreet');
+
+FixMyStreet::Map::set_map_class();
+my $r = Catalyst::Request->new( { base => URI->new('/'), uri => URI->new('http://fixmystreet.com/test') } );
+
+my $c = FixMyStreet::App->new( {
+ request => $r,
+});
+
+$mech->delete_user('test@example.com');
+my $user =
+ FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'test@example.com', name => 'Test User' } );
+ok $user, "created test user";
+
+my $dt = DateTime->now();
+
+
+my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+ {
+ postcode => 'SW1A 1AA',
+ council => '2504',
+ areas => ',105255,11806,11828,2247,2504,',
+ category => 'Other',
+ title => 'Test 2',
+ detail => 'Test 2 Detail',
+ used_map => 't',
+ name => 'Test User',
+ anonymous => 'f',
+ state => 'fixed',
+ confirmed => $dt->ymd . ' ' . $dt->hms,
+ lang => 'en-gb',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ send_questionnaire => 't',
+ latitude => '49.7668057243776',
+ longitude => '-7.55715980363992',
+ user_id => $user->id,
+ }
+);
+
+for my $test (
+ {
+ state => 'fixed',
+ colour => 'G',
+ },
+ {
+ state => 'fixed - user',
+ colour => 'G',
+ },
+ {
+ state => 'fixed - council',
+ colour => 'G',
+ },
+ {
+ state => 'confirmed',
+ colour => 'R',
+ },
+ {
+ state => 'investigating',
+ colour => 'R',
+ },
+ {
+ state => 'planned',
+ colour => 'R',
+ },
+ {
+ state => 'in progress',
+ colour => 'R',
+ },
+) {
+ subtest "pin colour for state $test->{state}" => sub {
+ $report->state($test->{state});
+ $report->update;
+
+ my ( $pins, $around_map_list, $nearby, $dist ) =
+ FixMyStreet::Map::map_pins( $c, 0, 0, 0, 0 );
+
+ ok $pins;
+ ok $around_map_list;
+ ok $nearby;
+ ok $dist;
+
+ my $id = $report->id;
+ my $colour = $test->{colour};
+
+ like $pins, qr#<a [^>]* /report/$id [^>]*>[^>]*/i/pin$colour#x, 'pin colour';
+ };
+}
+
+$mech->delete_user( $user );
+
+
+done_testing();
diff --git a/templates/web/default/admin/report_edit.html b/templates/web/default/admin/report_edit.html
index 9c38b014e..551f80127 100644
--- a/templates/web/default/admin/report_edit.html
+++ b/templates/web/default/admin/report_edit.html
@@ -19,7 +19,10 @@
<option [% 'selected ' IF !problem.anonymous %]value="0">[% loc('No') %]</option>
</select></li>
<li><label for="state">[% loc('State:') %]</label> <select name="state" id="state">
- [% FOREACH state IN [ ['confirmed', loc('Open')], ['fixed', loc('Fixed')], ['hidden', loc('Hidden')], ['partial', loc('Partial')],['unconfirmed',loc('Unconfirmed')] ] %]
+ [% FOREACH state IN [ ['confirmed', loc('Open')], ['investigating',
+ loc('Investigating')], ['planned', loc('Planned')], ['in progress',
+ loc('In Progress')], ['closed', loc('Closed')], ['fixed', loc('Fixed')], ['fixed - user',
+ loc('Fixed - User')], ['fixed - council', loc('Fixed - Council')], ['hidden', loc('Hidden')], ['partial', loc('Partial')],['unconfirmed',loc('Unconfirmed')] ] %]
<option [% 'selected ' IF state.0 == problem.state %] value="[% state.0 %]">[% state.1 %]</option>
[% END %]
</select></li>
diff --git a/templates/web/default/report/display.html b/templates/web/default/report/display.html
index 40c5f081f..25f3892a6 100644
--- a/templates/web/default/report/display.html
+++ b/templates/web/default/report/display.html
@@ -85,11 +85,23 @@
<textarea name="update" id="form_update" rows="7" cols="30">[% update.text | html %]</textarea>
</div>
- [% IF problem.state != 'fixed' %]
- <div class="checkbox">
- <input type="checkbox" name="fixed" id="form_fixed" value="1"[% ' checked' IF update.mark_fixed %]>
- <label for="form_fixed">[% loc('This problem has been fixed') %]</label>
- </div>
+ [% IF c.user && c.user.from_authority %]
+ <div class="form-field">
+ <label for="form_state">[% loc( 'State:' ) %]</label>
+ <select name="state" id="form_state">
+ [% FOREACH state IN [ ['confirmed', loc('Open')], ['investigating',
+ loc('Investigating')], ['planned', loc('Planned')], ['in progress',
+ loc('In Progress')], ['closed', loc('Closed')], ['fixed', loc('Fixed')] ] %]
+ <option [% 'selected ' IF state.0 == problem.state %] value="[% state.0 %]">[% state.1 %]</option>
+ [% END %]
+ </select>
+ [% ELSE %]
+ [% IF !problem.is_fixed %]
+ <div class="checkbox">
+ <input type="checkbox" name="fixed" id="form_fixed" value="1"[% fixed %]>
+ <label for="form_fixed">[% loc('This problem has been fixed') %]</label>
+ </div>
+ [% END %]
[% END %]
[% IF c.cobrand.allow_photo_upload %]
diff --git a/templates/web/default/report/updates.html b/templates/web/default/report/updates.html
index 910430114..95a2c7b38 100644
--- a/templates/web/default/report/updates.html
+++ b/templates/web/default/report/updates.html
@@ -12,6 +12,7 @@
[%- c.cobrand.extra_update_meta_text(update) -%]
[%- ", " _ loc( 'marked as fixed' ) IF update.mark_fixed %]
[%- ", " _ loc( 'reopened' ) IF update.mark_open %]
+ [%- ", " _ tprintf(loc( 'marked as %s' ), update.meta_problem_state) IF update.problem_state %]
</em></p>
[% IF c.cobrand.allow_update_reporting %]
diff --git a/web/css/core.css b/web/css/core.css
index 576437251..937bf533d 100644
--- a/web/css/core.css
+++ b/web/css/core.css
@@ -1,59 +1,47 @@
#mysociety blockquote {
border-left: solid 4px #666666;
- padding-left: 0.5em;
-}
-#mysociety blockquote h2, #mysociety blockquote p {
- margin: 0;
-}
+ padding-left: 0.5em; }
+ #mysociety blockquote h2, #mysociety blockquote p {
+ margin: 0; }
#mysociety dt {
font-weight: bold;
- margin-top: 0.5em;
-}
+ margin-top: 0.5em; }
#mysociety .gone {
color: #666666;
- background-color: #cccccc;
-}
+ background-color: #cccccc; }
#mysociety p.dev-site-notice, #mysociety p.error {
text-align: center;
color: #cc0000;
- font-size: larger;
-}
+ font-size: larger; }
#mysociety ul {
padding: 0 0 0 1.5em;
- margin: 0;
-}
+ margin: 0; }
#mysociety ul.error {
color: #cc0000;
background-color: #ffeeee;
padding-right: 4px;
text-align: left;
- font-size: larger;
-}
+ 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;
-}
+ text-align: left; }
#mysociety div.form-field {
- clear: both;
-}
+ clear: both; }
#mysociety #advert_thin {
width: 50%;
margin: 1em auto;
- border-top: dotted 1px #999999;
-}
+ border-top: dotted 1px #999999; }
#mysociety #advert_hfymp {
border-top: dotted 1px #999999;
- text-align: center;
-}
+ text-align: center; }
#mysociety p#expl {
text-align: center;
font-size: 150%;
- margin: 0 2em;
-}
+ margin: 0 2em; }
#mysociety #postcodeForm {
display: table;
_width: 33em;
@@ -63,23 +51,18 @@
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%;
-}
+ 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;
-}
+ width: 48%; }
+ #mysociety #front_intro p {
+ clear: both;
+ margin-top: 0; }
#mysociety #front_stats div {
text-align: center;
width: 5.5em;
@@ -87,58 +70,45 @@
-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;
-}
+ margin: 0 1em 1em; }
+ #mysociety #front_stats div big {
+ font-size: 150%;
+ display: block; }
#mysociety #front_recent {
float: right;
width: 48%;
- margin-bottom: 1em;
-}
+ margin-bottom: 1em; }
#mysociety #front_recent img, #mysociety #alert_recent img {
margin-right: 0.25em;
- margin-bottom: 0.25em;
-}
+ margin-bottom: 0.25em; }
#mysociety #front_recent > h2:first-child, #mysociety #front_intro > h2:first-child {
- margin-top: 0;
-}
+ margin-top: 0; }
#mysociety form {
- margin: 0;
-}
+ margin: 0; }
#mysociety label {
float: left;
text-align: right;
padding-right: 0.5em;
- width: 5em;
-}
+ width: 5em; }
#mysociety fieldset, #mysociety #fieldset {
border: none;
- padding: 0.5em;
-}
-#mysociety fieldset div, #mysociety #fieldset div {
- margin-top: 2px;
- clear: left;
-}
+ padding: 0.5em; }
+ #mysociety fieldset div, #mysociety #fieldset div {
+ margin-top: 2px;
+ clear: left; }
#mysociety legend {
- display: none;
-}
+ display: none; }
#mysociety #fieldset div.checkbox, #mysociety #problem_submit {
- padding-left: 5.5em;
-}
+ 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;
-}
+ cursor: hand; }
#mysociety #questionnaire label, #mysociety #alerts label {
- float: none;
-}
+ float: none; }
#mysociety .confirmed {
background-color: #ccffcc;
border: solid 2px #009900;
@@ -165,60 +135,48 @@
width: 231px;
position: absolute;
bottom: 0;
- right: 0;
-}
+ right: 0; }
#mysociety #map_box {
float: right;
width: 502px;
position: relative;
padding-left: 20px;
- background-color: #ffffff;
-}
+ background-color: #ffffff; }
#mysociety p#copyright {
float: right;
margin: 0 0 1em 0;
- font-size: 78%;
-}
+ font-size: 78%; }
#mysociety #map {
border: solid 1px #000000;
width: 500px;
height: 500px;
overflow: hidden;
position: relative;
- background-color: #f1f1f1;
-}
+ 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;
-}
+ 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;
-}
+ cursor: pointer; }
#mysociety form#mapForm .olTileImage {
- cursor: crosshair;
-}
+ cursor: crosshair; }
#mysociety #compass {
background-color: #ffffff;
border: solid 1px #000000;
@@ -226,73 +184,72 @@
color: #000000;
position: absolute;
top: 0px;
- left: 0px;
-}
-#mysociety #compass img {
- border: 0;
-}
+ left: 0px; }
+ #mysociety #compass img {
+ border: 0; }
#mysociety #text_map {
margin-top: 0.5em;
margin-bottom: 1em;
- font-size: 110%;
-}
+ font-size: 110%; }
#mysociety #text_no_map {
- margin-top: 0;
-}
+ margin-top: 0; }
#mysociety #sub_map_links {
float: right;
clear: right;
- margin-top: 0;
-}
+ margin-top: 0; }
#mysociety #fixed {
margin: 0 530px 1em 0;
padding: 5px;
text-align: center;
position: relative;
background-color: #ccffcc;
- border: solid 2px #009900;
-}
+ 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;
-}
+ border: solid 2px #990000; }
+#mysociety #closed {
+ margin: 0 530px 1em 0;
+ padding: 5px;
+ text-align: center;
+ position: relative;
+ background-color: #ccccff;
+ border: solid 2px #000099; }
+#mysociety #progress {
+ margin: 0 530px 1em 0;
+ padding: 5px;
+ text-align: center;
+ position: relative;
+ background-color: #ffffcc;
+ border: solid 2px #999900; }
#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;
-}
+ 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;
-}
+ margin: 0; }
#mysociety #nearby_lists h2 {
margin-top: 0.5em;
- margin-bottom: 0;
-}
+ margin-bottom: 0; }
#mysociety #alert_links {
- float: right;
-}
+ float: right; }
#mysociety #alert_links_area {
background-color: #ffeecc;
border: solid 1px #ff9900;
border-width: 1px 0;
padding: 3px 10px;
- margin: 0;
-}
+ margin: 0; }
#mysociety #rss_alert {
- text-decoration: none;
-}
-#mysociety #rss_alert span {
- text-decoration: underline;
-}
+ text-decoration: none; }
+ #mysociety #rss_alert span {
+ text-decoration: underline; }
#mysociety #email_alert_box {
display: none;
position: absolute;
@@ -300,92 +257,69 @@
font-size: 83%;
border: solid 1px #7399C3;
background-color: #eeeeff;
- color: #000000;
-}
+ color: #000000; }
#mysociety #email_alert_box p {
- margin: 0;
-}
+ margin: 0; }
#mysociety .council_sent_info {
- font-size: smaller;
-}
+ font-size: smaller; }
#mysociety #rss_items {
width: 62%;
- float: left;
-}
+ 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;
-}
+ margin: 0 0 1em 0.5em; }
#mysociety #rss_box {
padding: 10px;
- border: 1px solid #999999;
-}
+ border: 1px solid #999999; }
#mysociety #rss_feed {
list-style-type: none;
- margin-bottom: 2em;
-}
+ margin-bottom: 2em; }
#mysociety #rss_feed li {
- margin-bottom: 1em;
-}
+ margin-bottom: 1em; }
#mysociety #alert_or {
font-style: italic;
font-size: 125%;
- margin: 0;
-}
+ margin: 0; }
#mysociety #rss_list {
float: left;
- width: 47%;
-}
+ width: 47%; }
#mysociety #rss_list ul {
- list-style-type: none;
-}
+ list-style-type: none; }
#mysociety #rss_buttons {
float: right;
width: 35%;
text-align: center;
- margin-bottom: 2em;
-}
+ margin-bottom: 2em; }
#mysociety #rss_local {
margin-left: 1.5em;
- margin-bottom: 0;
-}
+ margin-bottom: 0; }
#mysociety #rss_local_alt {
- margin: 0 0 2em 4em;
-}
+ margin: 0 0 2em 4em; }
#mysociety #alert_photos {
text-align: center;
float: right;
width: 150px;
- margin-left: 0.5em;
-}
+ margin-left: 0.5em; }
#mysociety #alert_photos h2 {
- font-size: 100%;
-}
+ font-size: 100%; }
#mysociety #alert_photos img {
- margin-bottom: 0.25em;
-}
+ margin-bottom: 0.25em; }
#mysociety #col_problems, #mysociety #col_fixed {
float: left;
width: 48%;
- margin-right: 1em;
-}
+ margin-right: 1em; }
#mysociety .contact-details {
font-size: 80%;
- margin-top: 2em;
-}
+ margin-top: 2em; }
@media print {
#mysociety #map_box {
float: none;
- margin: 0 auto;
- }
+ margin: 0 auto; }
#mysociety #mysociety {
- max-width: none;
- }
+ max-width: none; }
#mysociety #side {
- margin-right: 0;
- }
-}
+ margin-right: 0; } }
diff --git a/web/css/core.scss b/web/css/core.scss
index 246a33167..cbf15f16b 100644
--- a/web/css/core.scss
+++ b/web/css/core.scss
@@ -319,6 +319,18 @@ $map_width: 500px;
border: solid 2px #990000;
}
+ #closed {
+ @include problem-banner;
+ background-color: #ccccff;
+ border: solid 2px #000099;
+ }
+
+ #progress {
+ @include problem-banner;
+ background-color: #ffffcc;
+ border: solid 2px #999900;
+ }
+
#updates {
div {
padding: 0 0 0.5em;