diff options
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’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; |