diff options
69 files changed, 398 insertions, 211 deletions
diff --git a/bin/update-schema b/bin/update-schema index e8f2e2cbd..eb44e4dda 100755 --- a/bin/update-schema +++ b/bin/update-schema @@ -194,6 +194,7 @@ else { # By querying the database schema, we can see where we're currently at # (assuming schema change files are never half-applied, which should be the case) sub get_db_version { + return '0044' if table_exists('contact_response_templates'); return '0043' if column_exists('users', 'area_id'); return '0042' if table_exists('user_planned_reports'); return '0041' if column_exists('users', 'is_superuser') && ! constraint_exists('user_body_permissions_permission_type_check'); diff --git a/db/downgrade_0044---0043.sql b/db/downgrade_0044---0043.sql new file mode 100644 index 000000000..d3a7642ad --- /dev/null +++ b/db/downgrade_0044---0043.sql @@ -0,0 +1,7 @@ +BEGIN; + +ALTER TABLE response_templates DROP COLUMN auto_response; + +DROP TABLE contact_response_templates; + +COMMIT; diff --git a/db/schema.sql b/db/schema.sql index b11bb30b7..c96059fb1 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -473,5 +473,12 @@ create table response_templates ( title text not null, text text not null, created timestamp not null default current_timestamp, + auto_response boolean NOT NULL DEFAULT 'f', unique(body_id, title) ); + +CREATE TABLE contact_response_templates ( + id serial NOT NULL PRIMARY KEY, + contact_id int REFERENCES contacts(id) NOT NULL, + response_template_id int REFERENCES response_templates(id) NOT NULL +); diff --git a/db/schema_0044-contact_response_templates.sql b/db/schema_0044-contact_response_templates.sql new file mode 100644 index 000000000..e85d99fb8 --- /dev/null +++ b/db/schema_0044-contact_response_templates.sql @@ -0,0 +1,12 @@ +BEGIN; + +CREATE TABLE contact_response_templates ( + id serial NOT NULL PRIMARY KEY, + contact_id int REFERENCES contacts(id) NOT NULL, + response_template_id int REFERENCES response_templates(id) NOT NULL +); + +ALTER TABLE response_templates + ADD COLUMN auto_response boolean NOT NULL DEFAULT 'f'; + +COMMIT; diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 652113734..66b46877f 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -309,7 +309,7 @@ sub body : Path('body') : Args(1) { $c->forward('update_contacts'); } - $c->forward('display_contacts'); + $c->forward('fetch_contacts'); return 1; } @@ -457,14 +457,14 @@ sub check_body_params : Private { } } -sub display_contacts : Private { +sub fetch_contacts : Private { my ( $self, $c ) = @_; my $contacts = $c->stash->{body}->contacts->search(undef, { order_by => [ 'category' ] } ); $c->stash->{contacts} = $contacts; $c->stash->{live_contacts} = $contacts->search({ deleted => 0 }); - if ( $c->get_param('text') && $c->get_param('text') == 1 ) { + if ( $c->get_param('text') && $c->get_param('text') eq '1' ) { $c->stash->{template} = 'admin/council_contacts.txt'; $c->res->content_type('text/plain; charset=utf-8'); return 1; @@ -893,57 +893,84 @@ sub categories_for_point : Private { sub templates : Path('templates') : Args(0) { my ( $self, $c ) = @_; - $c->detach( '/page_error_404_not_found' ) - unless $c->cobrand->moniker eq 'zurich'; - my $user = $c->user; - $self->templates_for_body($c, $user->from_body ); + if ($user->is_superuser) { + $c->forward('fetch_all_bodies'); + $c->stash->{template} = 'admin/templates_index.html'; + } elsif ( $user->from_body ) { + $c->forward('load_template_body', [ $user->from_body->id ]); + $c->res->redirect( $c->uri_for( 'templates', $c->stash->{body}->id ) ); + } else { + $c->detach( '/page_error_404_not_found' ); + } } sub templates_view : Path('templates') : Args(1) { my ($self, $c, $body_id) = @_; - $c->detach( '/page_error_404_not_found' ) - unless $c->cobrand->moniker eq 'zurich'; + $c->forward('load_template_body', [ $body_id ]); - # e.g. for admin + my @templates = $c->stash->{body}->response_templates->search( + undef, + { + order_by => 'title' + } + ); - my $body = $c->model('DB::Body')->find($body_id) - or $c->detach( '/page_error_404_not_found' ); + $c->stash->{response_templates} = \@templates; - $self->templates_for_body($c, $body); + $c->stash->{template} = 'admin/templates.html'; } sub template_edit : Path('templates') : Args(2) { my ( $self, $c, $body_id, $template_id ) = @_; - $c->detach( '/page_error_404_not_found' ) - unless $c->cobrand->moniker eq 'zurich'; - - my $body = $c->model('DB::Body')->find($body_id) - or $c->detach( '/page_error_404_not_found' ); - $c->stash->{body} = $body; + $c->forward('load_template_body', [ $body_id ]); my $template; if ($template_id eq 'new') { - $template = $body->response_templates->new({}); + $template = $c->stash->{body}->response_templates->new({}); } else { - $template = $body->response_templates->find( $template_id ) + $template = $c->stash->{body}->response_templates->find( $template_id ) or $c->detach( '/page_error_404_not_found' ); } + $c->forward('fetch_contacts'); + my @contacts = $template->contacts->all; + my @live_contacts = $c->stash->{live_contacts}->all; + my %active_contacts = map { $_->id => 1 } @contacts; + my @all_contacts = map { { + id => $_->id, + category => $_->category, + active => $active_contacts{$_->id}, + } } @live_contacts; + $c->stash->{contacts} = \@all_contacts; + if ($c->req->method eq 'POST') { - if ($c->get_param('delete_template') eq _("Delete template")) { + if ($c->get_param('delete_template') && $c->get_param('delete_template') eq _("Delete template")) { + $template->contact_response_templates->delete_all; $template->delete; } else { $template->title( $c->get_param('title') ); - $template->text ( $c->get_param('text') ); + $template->text( $c->get_param('text') ); + $template->auto_response( $c->get_param('auto_response') ? 1 : 0 ); $template->update_or_insert; + + my @live_contact_ids = map { $_->id } @live_contacts; + my @new_contact_ids = grep { $c->get_param("contacts[$_]") } @live_contact_ids; + $template->contact_response_templates->search({ + contact_id => { '!=' => \@new_contact_ids }, + })->delete; + foreach my $contact_id (@new_contact_ids) { + $template->contact_response_templates->find_or_create({ + contact_id => $contact_id, + }); + } } - $c->res->redirect( $c->uri_for( 'templates', $body->id ) ); + $c->res->redirect( $c->uri_for( 'templates', $c->stash->{body}->id ) ); } $c->stash->{response_template} = $template; @@ -951,22 +978,24 @@ sub template_edit : Path('templates') : Args(2) { $c->stash->{template} = 'admin/template_edit.html'; } +sub load_template_body : Private { + my ($self, $c, $body_id) = @_; -sub templates_for_body { - my ( $self, $c, $body ) = @_; - - $c->stash->{body} = $body; + my $zurich_user = $c->user->from_body && $c->cobrand->moniker eq 'zurich'; + my $has_permission = $c->user->has_body_permission_to('template_edit') && + $c->user->from_body->id eq $body_id; - my @templates = $body->response_templates->search( - undef, - { - order_by => 'title' - } - ); + unless ( $c->user->is_superuser || $zurich_user || $has_permission ) { + $c->detach( '/page_error_404_not_found' ); + } - $c->stash->{response_templates} = \@templates; + # Regular users can only view their own body's templates + if ( !$c->user->is_superuser && $body_id ne $c->user->from_body->id ) { + $c->res->redirect( $c->uri_for( 'templates', $c->user->from_body->id ) ); + } - $c->stash->{template} = 'admin/templates.html'; + $c->stash->{body} = $c->model('DB::Body')->find($body_id) + or $c->detach( '/page_error_404_not_found' ); } sub users: Path('users') : Args(0) { @@ -1182,7 +1211,7 @@ sub user_edit : Path('user_edit') : Args(1) { my $user = $c->cobrand->users->find( { id => $id } ); $c->detach( '/page_error_404_not_found' ) unless $user; - unless ( $c->user->is_superuser || ( $c->user->has_permission_to('user_edit', $c->user->from_body->id) ) ) { + unless ( $c->user->is_superuser || $c->user->has_body_permission_to('user_edit') ) { $c->detach('/page_error_403_access_denied', []); } @@ -1219,7 +1248,7 @@ sub user_edit : Path('user_edit') : Args(1) { # set from_body to the same value as their own from_body. if ( $c->user->is_superuser ) { $user->from_body( $c->get_param('body') || undef ); - } elsif ( $c->user->has_permission_to('user_assign_body', $c->user->from_body->id ) && + } elsif ( $c->user->has_body_permission_to('user_assign_body') && $c->get_param('body') && $c->get_param('body') eq $c->user->from_body->id ) { $user->from_body( $c->user->from_body ); } else { diff --git a/perllib/FixMyStreet/App/Controller/My.pm b/perllib/FixMyStreet/App/Controller/My.pm index b15750c98..b7fabcf4c 100644 --- a/perllib/FixMyStreet/App/Controller/My.pm +++ b/perllib/FixMyStreet/App/Controller/My.pm @@ -41,7 +41,7 @@ sub planned : Local : Args(0) { my ( $self, $c ) = @_; $c->detach('/page_error_403_access_denied', []) - unless $c->user->from_body && $c->user->has_permission_to('planned_reports', $c->user->from_body->id); + unless $c->user->has_body_permission_to('planned_reports'); $c->stash->{problems_rs} = $c->user->active_planned_reports; $c->forward('get_problems'); diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index ee110a18b..a58f50b18 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -646,7 +646,7 @@ sub admin_pages { 'summary' => [_('Summary'), 0], 'bodies' => [_('Bodies'), 1], 'reports' => [_('Reports'), 2], - 'timeline' => [_('Timeline'), 3], + 'timeline' => [_('Timeline'), 4], 'users' => [_('Users'), 5], 'flagged' => [_('Flagged'), 6], 'stats' => [_('Stats'), 7], @@ -661,6 +661,12 @@ sub admin_pages { if ( $user->is_superuser ) { $pages->{config} = [ _('Configuration'), 8]; }; + # And some that need special permissions + if ( $user->is_superuser || $user->has_body_permission_to('template_edit') ) { + $pages->{templates} = [_('Templates'), 3], + $pages->{template_edit} = [undef, undef], + }; + return $pages; } @@ -711,6 +717,9 @@ sub available_permissions { user_assign_body => _("Grant access to the admin"), user_assign_areas => _("Assign users to areas"), # future use }, + _("Bodies") => { + template_edit => _("Add/edit response templates"), + }, }; } diff --git a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm index 30240f61e..f8079565d 100644 --- a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm +++ b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm @@ -10,6 +10,11 @@ sub council_name { return 'Oxfordshire County Council'; } sub council_url { return 'oxfordshire'; } sub is_two_tier { return 1; } +sub is_council_with_case_management { + # XXX Change this to return 1 when OCC FMSfC goes live. + return FixMyStreet->config('STAGING_SITE'); +} + sub map_type { 'OSM' } sub base_url { diff --git a/perllib/FixMyStreet/DB/Result/Contact.pm b/perllib/FixMyStreet/DB/Result/Contact.pm index 58d8e58de..ea9b656aa 100644 --- a/perllib/FixMyStreet/DB/Result/Contact.pm +++ b/perllib/FixMyStreet/DB/Result/Contact.pm @@ -55,10 +55,16 @@ __PACKAGE__->belongs_to( { id => "body_id" }, { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, ); +__PACKAGE__->has_many( + "contact_response_templates", + "FixMyStreet::DB::Result::ContactResponseTemplate", + { "foreign.contact_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2013-09-10 17:11:54 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hq/BFHDEu4OUI4MSy3OyHg +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-08-24 11:29:04 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CXUabm3Yd11OoIYJceSPag __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); @@ -68,6 +74,8 @@ use namespace::clean -except => [ 'meta' ]; with 'FixMyStreet::Roles::Extra'; +__PACKAGE__->many_to_many( response_templates => 'contact_response_templates', 'response_template' ); + sub get_metadata_for_input { my $self = shift; my $id_field = $self->id_field; diff --git a/perllib/FixMyStreet/DB/Result/ContactResponseTemplate.pm b/perllib/FixMyStreet/DB/Result/ContactResponseTemplate.pm new file mode 100644 index 000000000..3c777533c --- /dev/null +++ b/perllib/FixMyStreet/DB/Result/ContactResponseTemplate.pm @@ -0,0 +1,46 @@ +use utf8; +package FixMyStreet::DB::Result::ContactResponseTemplate; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; +__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->table("contact_response_templates"); +__PACKAGE__->add_columns( + "id", + { + data_type => "integer", + is_auto_increment => 1, + is_nullable => 0, + sequence => "contact_response_templates_id_seq", + }, + "contact_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, + "response_template_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, +); +__PACKAGE__->set_primary_key("id"); +__PACKAGE__->belongs_to( + "contact", + "FixMyStreet::DB::Result::Contact", + { id => "contact_id" }, + { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, +); +__PACKAGE__->belongs_to( + "response_template", + "FixMyStreet::DB::Result::ResponseTemplate", + { id => "response_template_id" }, + { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-08-24 11:29:04 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:d6niNsxi2AsijhvJSuQeKw + + +# You can replace this text with custom code or comments, and it will be preserved on regeneration +1; diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index 308fba71f..8236524d6 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -678,6 +678,13 @@ sub duration_string { } else { $body = $problem->body( $c ); } + if ( $c->cobrand->can('get_body_handler_for_problem') ) { + my $handler = $c->cobrand->get_body_handler_for_problem( $problem ); + if ( $handler->can('is_council_with_case_management') && $handler->is_council_with_case_management ) { + return sprintf(_('Received by %s moments later'), $body); + } + } + return unless $problem->whensent; return sprintf(_('Sent to %s %s later'), $body, Utils::prettify_duration($problem->whensent->epoch - $problem->confirmed->epoch, 'minute') ); diff --git a/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm b/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm index d189bf3ec..0d4377dba 100644 --- a/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm +++ b/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm @@ -31,6 +31,8 @@ __PACKAGE__->add_columns( is_nullable => 0, original => { default_value => \"now()" }, }, + "auto_response", + { data_type => "boolean", default_value => \"false", is_nullable => 0 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("response_templates_body_id_title_key", ["body_id", "title"]); @@ -40,11 +42,18 @@ __PACKAGE__->belongs_to( { id => "body_id" }, { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, ); +__PACKAGE__->has_many( + "contact_response_templates", + "FixMyStreet::DB::Result::ContactResponseTemplate", + { "foreign.response_template_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-07-20 14:38:36 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ECFQLMxOFGwv7cwfHLlszw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-08-24 11:29:04 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:KRm0RHbtrzuxzH0S/UAsdw +__PACKAGE__->many_to_many( contacts => 'contact_response_templates', 'contact' ); # You can replace this text with custom code or comments, and it will be preserved on regeneration 1; diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm index 697cfedf6..6444cfe6a 100644 --- a/perllib/FixMyStreet/DB/Result/User.pm +++ b/perllib/FixMyStreet/DB/Result/User.pm @@ -254,6 +254,29 @@ sub has_permission_to { return $permission ? 1 : undef; } +=head2 has_body_permission_to + +Checks if the User has a from_body set, and the specified permission on that body. + +Instead of saying: + + ($user->from_body && $user->has_permission_to('user_edit', $user->from_body->id)) + +You can just say: + + $user->has_body_permission_to('user_edit') + +NB unlike has_permission_to, this doesn't blindly return 1 if the user is a superuser. + +=cut + +sub has_body_permission_to { + my ($self, $permission_type) = @_; + return unless $self->from_body; + + return $self->has_permission_to($permission_type, $self->from_body->id); +} + sub contributing_as { my ($self, $other, $c, $bodies) = @_; $bodies = join(',', keys %$bodies) if ref $bodies eq 'HASH'; diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm index c3583bb3e..ee9631bdf 100644 --- a/perllib/FixMyStreet/TestMech.pm +++ b/perllib/FixMyStreet/TestMech.pm @@ -600,12 +600,21 @@ sub delete_body { my $body = shift; $mech->delete_problems_for_body($body->id); - $body->contacts->delete; + $mech->delete_contact($_) for $body->contacts; $mech->delete_user($_) for $body->users; + $_->delete for $body->response_templates; $body->body_areas->delete; $body->delete; } +sub delete_contact { + my $mech = shift; + my $contact = shift; + + $contact->contact_response_templates->delete_all; + $contact->delete; +} + sub delete_problems_for_body { my $mech = shift; my $body = shift; diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t index 94a8d28f2..f7dcd4023 100644 --- a/t/app/controller/admin.t +++ b/t/app/controller/admin.t @@ -15,6 +15,7 @@ my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2'); my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council', id => 2237); +my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' ); my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire); my $bromley = $mech->create_body_ok(2482, 'Bromley Council', id => 2482); @@ -1175,6 +1176,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, + "permissions[template_edit]" => undef, }, changes => { name => 'Changed User', @@ -1205,6 +1207,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, + "permissions[template_edit]" => undef, }, changes => { email => 'changed@example.com', @@ -1235,6 +1238,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, + "permissions[template_edit]" => undef, }, changes => { body => $southend->id, @@ -1265,6 +1269,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, + "permissions[template_edit]" => undef, }, changes => { flagged => 'on', @@ -1295,6 +1300,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, + "permissions[template_edit]" => undef, }, changes => { flagged => undef, @@ -1325,6 +1331,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, + "permissions[template_edit]" => undef, }, changes => { is_superuser => 'on', @@ -1343,6 +1350,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]", "permissions[user_assign_body]", "permissions[user_assign_areas]", + "permissions[template_edit]", ], log_count => 5, log_entries => [qw/edit edit edit edit edit/], @@ -1375,6 +1383,7 @@ FixMyStreet::override_config { "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, + "permissions[template_edit]" => undef, }, log_count => 5, log_entries => [qw/edit edit edit edit edit/], @@ -1490,16 +1499,43 @@ subtest "Users with from_body can't access fixmystreet.com admin" => sub { }; }; -$mech->log_out_ok; -$user2->user_body_permissions->delete_all; -$oxfordshireuser->user_body_permissions->delete_all; +subtest "response templates can be added" => sub { + is $oxfordshire->response_templates->count, 0, "No response templates yet"; + $mech->log_in_ok( $superuser->email ); + $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" ); + + my $fields = { + title => "Report acknowledgement", + text => "Thank you for your report. We will respond shortly.", + auto_response => undef, + "contacts[".$oxfordshirecontact->id."]" => 1, + }; + $mech->submit_form_ok( { with_fields => $fields } ); + + is $oxfordshire->response_templates->count, 1, "Response template was added"; +}; + +subtest "response templates are included on page" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'oxfordshire' ], + }, sub { + $report->update({ category => $oxfordshirecontact->category, bodies_str => $oxfordshire->id }); + $mech->log_in_ok( $oxfordshireuser->email ); + $mech->get_ok("/report/" . $report->id); + $mech->content_contains( $oxfordshire->response_templates->first->text ); + + $mech->log_out_ok; + }; +}; + +$mech->log_out_ok; $mech->delete_user( $user ); $mech->delete_user( $user2 ); $mech->delete_user( $user3 ); $mech->delete_user( $superuser ); -$mech->delete_user( $oxfordshireuser ); $mech->delete_user( 'test4@example.com' ); +$mech->delete_body( $oxfordshire ); done_testing(); diff --git a/t/app/controller/admin_permissions.t b/t/app/controller/admin_permissions.t index 3809a9d67..2c271ba4c 100644 --- a/t/app/controller/admin_permissions.t +++ b/t/app/controller/admin_permissions.t @@ -167,7 +167,7 @@ FixMyStreet::override_config { "permissions[user_assign_areas]" => undef, } } ); - ok $user2->has_permission_to("moderate", $user2->from_body->id), "user2 has been granted moderate permission"; + ok $user2->has_body_permission_to("moderate"), "user2 has been granted moderate permission"; }; $oxfordshireuser->user_body_permissions->create({ diff --git a/templates/web/base/about/iphone.html b/templates/web/base/about/iphone.html deleted file mode 100755 index 8f7992713..000000000 --- a/templates/web/base/about/iphone.html +++ /dev/null @@ -1,52 +0,0 @@ -[% INCLUDE header.html - title = 'FixMyStreet for iPhone screenshots' -%] - -<h1>iPhone simulator simulator</h1> - -[% - SET screens = [ - [ "iphone-1start.png", 'Click the image to progress through the flow of using the iPhone FixMyStreet application. - <br>When launched, the user’s location automatically gets fetched…' ], - [ "iphone-2locfound.png", 'They want to take a photo.' ], - [ "iphone-pickpicture1.png", 'The simulator doesn’t have a camera, so we’re taken to the photo albums. Let’s pick Hawaii.' ], - [ "iphone-pickpicture2.png", 'That red clouds photo looks nice.' ], - [ "iphone-pickpicture3.png", 'After any moving or scaling we want, we select the photo.' ], - [ "iphone-3picture.png", 'Okay, now we need to edit the summary of the report.' ], - [ "iphone-editsummary.png", 'Enter some text.' ], - [ "iphone-editsummary2.png", 'And done.' ], - [ "iphone-4subject.png", 'I haven’t entered all my details yet, so that’s next.' ], - [ "iphone-5details.png", 'Your details are remembered so you only have to enter them once.' ], - [ "iphone-6emailkeyboard.png", 'The iPhone has different keyboards, this is the email one.' ], - [ "iphone-5details.png", 'Right, we need to enter a name.' ], - [ "iphone-editname.png", 'Slightly different keyboard to the email one.' ], - [ "iphone-detailsdone.png", 'Okay, details entered.' ], - [ "iphone-allready.png", 'That’s everything, hit Report!' ], - [ "iphone-7uploading.png", 'Uploading…' ], - [ "iphone-8response.png", 'The simulator always thinks it’s in the US, which FixMyStreet won’t like very much.' ], - [ "iphone-allready.png", 'Ah well, let’s read the About page instead' ], - [ "iphone-9about.png", 'Donate? :)' ], -]; -%] - -<script type="text/javascript"> -document.write('<style type="text/css">.vv { display: none; }</style>'); -function show(a) { - if (a==[% screens.size %]) b = 1; - else b = a+1; - document.getElementById('d' + a).style.display='none'; - document.getElementById('d' + b).style.display='block'; -} -</script> - -[% FOR screen IN screens %] - - <div id='d[% loop.count %]'[% " class='vv'" IF NOT loop.first %]> - <p>[% screen.1 %]</p> - <p align='center'><a onclick='show([% loop.count %]);return false' href='#d[% loop.count + 1 %]'><img src='[% screen.0 %]' width=414 border=0 height=770></a></p> - </div> - -[% END %] - -[% INCLUDE footer.html %] - diff --git a/templates/web/base/admin/report_edit.html b/templates/web/base/admin/report_edit.html index 48a02593b..96e59d1c4 100644 --- a/templates/web/base/admin/report_edit.html +++ b/templates/web/base/admin/report_edit.html @@ -81,7 +81,7 @@ class="admin-offsite-link">[% problem.latitude %], [% problem.longitude %]</a> ([% problem.send_method_used %]) [% END %] [% IF problem.state == 'confirmed' AND problem.whensent %] - <input onclick="return confirm('[% loc('You really want to resend?') %]')" type="submit" name="resend" value="[% loc('Resend report') %]"> + <input data-confirm="[% loc('Are you sure?') %]" type="submit" name="resend" value="[% loc('Resend report') %]"> [% ELSIF NOT problem.whensent %] <input type="submit" name="mark_sent" value="[% loc('Mark as sent') %]"> [% END %] diff --git a/templates/web/zurich/admin/response_templates_select.html b/templates/web/base/admin/response_templates_select.html index 853956a0d..664d1d20a 100644 --- a/templates/web/zurich/admin/response_templates_select.html +++ b/templates/web/base/admin/response_templates_select.html @@ -1,6 +1,6 @@ <div class="response_templates_select"> <select id="templates_for_[% for %]" class="js-template-name" data-for="[% for %]"> - <option value="">[% loc('Choose a template') %]</option> + <option value="">[% loc('--Choose a template--') %]</option> [% FOR t IN problem.response_templates %] <option value="[% t.text | html %]"> [% t.title | html %] </option> [% END %] diff --git a/templates/web/base/admin/template_edit.html b/templates/web/base/admin/template_edit.html new file mode 100644 index 000000000..54058a04c --- /dev/null +++ b/templates/web/base/admin/template_edit.html @@ -0,0 +1,50 @@ +[% INCLUDE 'admin/header.html' title=tprintf(loc('Response Template for %s'), body.name) -%] +[% rt = response_template %] + +[% UNLESS rt.id %]<h3>[% loc('New template') %]</h3>[% END %] + +<form method="post" + action="[% c.uri_for('templates', body.id, rt.id || 'new' ) %]" + enctype="application/x-www-form-urlencoded" + accept-charset="utf-8" + class="validate"> + + <p> + <strong>[% loc('Title:') %] </strong> + <input type="text" name="title" class="required" size="30" value="[% rt.title| html %]"> + </p> + <p> + <strong>[% loc('Text:') %] </strong> + <textarea name="text" class="required">[% rt.text |html %]</textarea> + </p> + <p> + <label> + <strong>[% loc('Auto-response:') %]</strong> + <input type="checkbox" name="auto_response" [% 'checked' IF rt.auto_response %] /> + </label> + </p> + <p> + <strong>[% loc('Categories:') %]</strong> + <ul> + [% FOR contact IN contacts %] + <li> + <label> + <input type="checkbox" name="contacts[[% contact.id %]]" [% 'checked' IF contact.active %]/> + [% contact.category %] + </label> + </li> + [% END %] + </ul> + </p> + <p> + <input type="hidden" name="token" value="[% csrf_token %]" > + <input type="submit" name="Edit templates" value="[% rt.id ? loc('Save changes') : loc('Create template') %]" > + </p> + [% IF rt.id %] + <p> + <input class="delete" type="submit" name="delete_template" value="[% loc('Delete template') %]"> + </p> + [% END %] +</form> + +[% INCLUDE 'admin/footer.html' %] diff --git a/templates/web/zurich/admin/templates.html b/templates/web/base/admin/templates.html index d3b334022..25cd181aa 100644 --- a/templates/web/zurich/admin/templates.html +++ b/templates/web/base/admin/templates.html @@ -1,6 +1,8 @@ [% INCLUDE 'admin/header.html' title=tprintf(loc('Response Templates for %s'), body.name) -%] -<h2> [% tprintf(loc('Response Templates for %s'), body.name) %] </h2> +[% IF c.cobrand.moniker == 'zurich' %] + <h2> [% tprintf(loc('Response Templates for %s'), body.name) %] </h2> +[% END %] <table> <thead> diff --git a/templates/web/base/admin/templates_index.html b/templates/web/base/admin/templates_index.html new file mode 100644 index 000000000..1f45b84de --- /dev/null +++ b/templates/web/base/admin/templates_index.html @@ -0,0 +1,11 @@ +[% INCLUDE 'admin/header.html' title=loc('Response Templates') -%] + +<ul> + [% FOR body IN bodies %] + <li> + <a href="/admin/templates/[% body.id %]">[% body.name %]</a> + </li> + [% END %] +</ul> + +[% INCLUDE 'admin/footer.html' %] diff --git a/templates/web/base/admin/user-form.html b/templates/web/base/admin/user-form.html index c22480011..b05f15355 100644 --- a/templates/web/base/admin/user-form.html +++ b/templates/web/base/admin/user-form.html @@ -49,7 +49,7 @@ [% loc("Staff users have permission to log in to the admin.") %] </p> </div> - [% loc('Staff:') %] <input type="checkbox" id="body" name="body" value="[% c.user.from_body.id %]" [% user.from_body.id == c.user.from_body.id ? ' checked' : '' %] [% 'disabled' UNLESS c.user.has_permission_to('user_assign_body', c.user.from_body.id) %]> + [% loc('Staff:') %] <input type="checkbox" id="body" name="body" value="[% c.user.from_body.id %]" [% user.from_body.id == c.user.from_body.id ? ' checked' : '' %] [% 'disabled' UNLESS c.user.is_superuser OR c.user.has_body_permission_to('user_assign_body') %]> </li> [% END %] @@ -116,7 +116,7 @@ [% FOREACH permission IN group.value %] <li> <label> - <input type="checkbox" id="perms_[% permission.key %]" name="permissions[[% permission.key %]]" [% "checked" IF user.has_permission_to(permission.key, user.from_body.id) %]> + <input type="checkbox" id="perms_[% permission.key %]" name="permissions[[% permission.key %]]" [% "checked" IF user.has_body_permission_to(permission.key) %]> [% permission.value %] </label> </li> diff --git a/templates/web/base/admin/users.html b/templates/web/base/admin/users.html index 19a3de03c..dfff77ee6 100644 --- a/templates/web/base/admin/users.html +++ b/templates/web/base/admin/users.html @@ -25,7 +25,7 @@ <td>[% PROCESS value_or_nbsp value=user.name %]</td> <td><a href="[% c.uri_for( 'reports', search => user.email ) %]">[% PROCESS value_or_nbsp value=user.email %]</a></td> <td>[% PROCESS value_or_nbsp value=user.from_body.name %] - [% IF user.from_body AND user.has_permission_to('moderate', user.from_body.id) %] * [% END %] + [% IF user.has_body_permission_to('moderate') %] * [% END %] </td> [% IF c.cobrand.moniker != 'zurich' %] <td>[% user.flagged == 2 ? loc('(Email in abuse table)') : user.flagged ? loc('Yes') : ' ' %]</td> diff --git a/templates/web/base/report/_council_sent_info.html b/templates/web/base/report/_council_sent_info.html index affc73414..dca74f994 100644 --- a/templates/web/base/report/_council_sent_info.html +++ b/templates/web/base/report/_council_sent_info.html @@ -1,6 +1,6 @@ -[% IF problem.whensent || problem.can_display_external_id %] +[% SET duration_clause = problem.duration_string(c) %] +[% IF duration_clause || problem.can_display_external_id %] <p class="council_sent_info"> - [% SET duration_clause = problem.duration_string(c) IF problem.whensent %] [%- IF problem.can_display_external_id %] [%- IF duration_clause %] [%- external_ref_clause = tprintf(loc('Council ref: %s'), problem.external_id) %] diff --git a/templates/web/base/report/display_tools.html b/templates/web/base/report/display_tools.html index 590f81593..052ffb8a5 100644 --- a/templates/web/base/report/display_tools.html +++ b/templates/web/base/report/display_tools.html @@ -1,9 +1,9 @@ <div class="shadow-wrap"> <ul id="key-tools"> - [% IF c.user_exists AND c.cobrand.users_can_hide AND c.user.belongs_to_body( c.cobrand.council_id ) %] + [% IF c.user_exists AND c.cobrand.users_can_hide AND c.user.belongs_to_body( problem.bodies_str ) %] <li><form method="post" action="/report/delete/[% problem.id %]" id="remove-from-site-form"> <input type="hidden" name="token" value="[% csrf_token %]"> - <input type="submit" id="key-tool-report-abuse" class="abuse" value="Remove from site"> + <input type="submit" id="key-tool-report-abuse" class="abuse" data-confirm="[% loc('Are you sure?') %]" value="[% loc('Remove from site') %]"> </form></li> [% ELSIF c.cobrand.moniker != 'zurich' %] <li><a rel="nofollow" id="key-tool-report-abuse" class="abuse" href="[% c.uri_for( '/contact', { id => problem.id } ) %]">[% loc('Report abuse' ) %]</a></li> diff --git a/templates/web/base/report/new/extra_name.html b/templates/web/base/report/new/extra_name.html index dede1000c..2838645af 100644 --- a/templates/web/base/report/new/extra_name.html +++ b/templates/web/base/report/new/extra_name.html @@ -6,7 +6,7 @@ [% title = '' %] [% IF fms_extra_title %][% title = fms_extra_title | upper %] [% ELSIF c.user && c.user.title %][% title = c.user.title | upper %][% END %] -<select class="form-focus-trigger required" id="form_fms_extra_title" +<select class="form-focus-trigger required js-form-name" id="form_fms_extra_title" name="fms_extra_title"> <option></option> <option value="MR"[% ' selected' IF title == 'MR' %]>Mr</option> diff --git a/templates/web/base/report/new/form_report.html b/templates/web/base/report/new/form_report.html index 007d98b76..d9320d166 100644 --- a/templates/web/base/report/new/form_report.html +++ b/templates/web/base/report/new/form_report.html @@ -12,11 +12,11 @@ [% need_to_show_category_selector = 1 %] [% END %] - <label for="form_title">[% loc('One-line summary') %] [% INCLUDE 'report/public_label.html' %]</label> + <label for="form_title">[% loc('Summarise the problem') %] [% INCLUDE 'report/public_label.html' %]</label> [% IF field_errors.title %] <p class='form-error'>[% field_errors.title %]</p> [% END %] - <input type="text" value="[% report.title | html %]" name="title" id="form_title" placeholder="[% loc('What’s the issue, and where is it?') %]" required> + <input type="text" value="[% report.title | html %]" name="title" id="form_title" placeholder="[% loc('10 inch pothole on Example St, near post box') %]" required> [% IF c.cobrand.allow_photo_upload %] <input type="hidden" name="upload_fileid" value="[% upload_fileid %]"> @@ -46,11 +46,11 @@ [% TRY %][% PROCESS 'report/new/after_photo.html' %][% CATCH file %][% END %] - <label for="form_detail">[% loc('Description') %] [% INCLUDE 'report/public_label.html' %]</label> + <label for="form_detail">[% loc('Explain what’s wrong') %] [% INCLUDE 'report/public_label.html' %]</label> [% IF field_errors.detail %] <p class='form-error'>[% field_errors.detail %]</p> [% END %] - <textarea rows="7" cols="26" name="detail" id="form_detail" placeholder="[% loc('Explain what’s wrong, exactly where it is, and how long it’s been there…') %]" required>[% report.detail | html %]</textarea> + <textarea rows="7" cols="26" name="detail" id="form_detail" placeholder="[% loc('This pothole has been here for two months and…') %]" required>[% report.detail | html %]</textarea> [% TRY %][% PROCESS 'report/new/inline-tips.html' %][% CATCH file %][% END %] diff --git a/templates/web/base/report/new/form_user_loggedin.html b/templates/web/base/report/new/form_user_loggedin.html index 1f941a6d1..add4fdbd3 100644 --- a/templates/web/base/report/new/form_user_loggedin.html +++ b/templates/web/base/report/new/form_user_loggedin.html @@ -46,7 +46,7 @@ [% IF field_errors.name %] <p class='form-error'>[% field_errors.name %]</p> [% END %] - <input type="text" class="validName" value="[% report.name | html %]" name="name" id="form_name"> + <input type="text" class="validName js-form-name" value="[% report.name | html %]" name="name" id="form_name"> [%# if there is nothing in the name field then set check box as default on form %] <div class="checkbox-group"> @@ -62,6 +62,6 @@ </div> <div class="form-txt-submit-box"> - <input class="green-btn" type="submit" id="submit_register" name="submit_register" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Submit') %]"> </div> </div> diff --git a/templates/web/base/report/new/form_user_loggedout_by_email.html b/templates/web/base/report/new/form_user_loggedout_by_email.html index 1ad07c540..0b2f3859e 100644 --- a/templates/web/base/report/new/form_user_loggedout_by_email.html +++ b/templates/web/base/report/new/form_user_loggedout_by_email.html @@ -14,7 +14,7 @@ <p class='form-error'>[% field_errors.name %]</p> [% END %] - <input type="text" class="form-focus-trigger validName" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> + <input type="text" class="form-focus-trigger validName js-form-name" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> [%# if there is nothing in the name field then set check box as default on form %] <div class="checkbox-group"> @@ -36,6 +36,6 @@ <div class="form-txt-submit-box form-focus-hidden"> <input type="password" name="password_register" id="password_register" value="" placeholder="[% loc('Enter a password') %]"> - <input class="green-btn" type="submit" id="submit_register" name="submit_register" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Submit') %]"> </div> </div> diff --git a/templates/web/base/report/new/form_user_loggedout_password.html b/templates/web/base/report/new/form_user_loggedout_password.html index c9d65e43e..0f234aeba 100644 --- a/templates/web/base/report/new/form_user_loggedout_password.html +++ b/templates/web/base/report/new/form_user_loggedout_password.html @@ -8,7 +8,7 @@ [% END %] <div class="form-txt-submit-box"> <input type="password" name="password_sign_in" id="password_sign_in" placeholder="[% loc('Your password') %]" value=""> - <input class="green-btn" type="submit" id="submit_sign_in" name="submit_sign_in" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_sign_in" type="submit" name="submit_sign_in" value="[% loc('Submit') %]"> </div> <div class="checkbox-group"> diff --git a/templates/web/base/report/update-form.html b/templates/web/base/report/update-form.html index 97e0df779..49d011c0e 100644 --- a/templates/web/base/report/update-form.html +++ b/templates/web/base/report/update-form.html @@ -22,7 +22,7 @@ [% END %] [% IF c.user_exists %] [% INCLUDE 'report/update/form_name.html' %] - <div class="clearfix"><input class="final-submit green-btn" type="submit" id="update_post" value="[% loc('Post') %]"></div> + <div class="clearfix"><input class="final-submit green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Post') %]"></div> [% ELSIF oauth_need_email %] [% INCLUDE 'report/update/form_user_loggedout_email.html' required = 1 %] <div id="form_sign_in"> diff --git a/templates/web/base/report/update/form_name.html b/templates/web/base/report/update/form_name.html index e65ab1790..ef8efd296 100644 --- a/templates/web/base/report/update/form_name.html +++ b/templates/web/base/report/update/form_name.html @@ -25,8 +25,7 @@ <p class='form-error'>[% field_errors.name %]</p> [% END %] -<input type="text" - [%- IF c.cobrand.moniker.match('fixmystreet|bromley') AND problem.bodies_str == '2482' %]class="validName" [% END -%] +<input type="text" class="validName js-form-name" name="name" id="form_name" value="[% update.name || c.user.name | html %]" placeholder="[% loc('Your name') %]"> <div class="checkbox-group"> diff --git a/templates/web/base/report/update/form_update.html b/templates/web/base/report/update/form_update.html index 0645cad41..55125ba4b 100644 --- a/templates/web/base/report/update/form_update.html +++ b/templates/web/base/report/update/form_update.html @@ -27,6 +27,9 @@ [% END %] <label for="form_update">[% loc( 'Update' ) %]</label> +[% IF c.user && c.user.belongs_to_body( problem.bodies_str ) %] + [% INCLUDE 'admin/response_templates_select.html' for='form_update' %] +[% END %] [% IF field_errors.update %] <div class='form-error'>[% field_errors.update %]</div> [% END %] diff --git a/templates/web/base/report/update/form_user_loggedout_by_email.html b/templates/web/base/report/update/form_user_loggedout_by_email.html index 672f76ed9..aae37502b 100644 --- a/templates/web/base/report/update/form_user_loggedout_by_email.html +++ b/templates/web/base/report/update/form_user_loggedout_by_email.html @@ -11,7 +11,7 @@ <div class="form-txt-submit-box"> <input type="password" name="password_register" id="password_register" value="" placeholder="[% loc('Enter a password') %]"> - <input class="green-btn" type="submit" name="submit_register" id="submit_register" value="[% loc('Post') %]"> + <input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Post') %]"> </div> </div> diff --git a/templates/web/base/report/update/form_user_loggedout_password.html b/templates/web/base/report/update/form_user_loggedout_password.html index 103df1098..593ccf3de 100644 --- a/templates/web/base/report/update/form_user_loggedout_password.html +++ b/templates/web/base/report/update/form_user_loggedout_password.html @@ -7,7 +7,7 @@ [% END %] <div class="form-txt-submit-box"> <input type="password" name="password_sign_in" id="password_sign_in" value="" placeholder="[% loc('Your password') %]"> - <input class="green-btn" type="submit" name="submit_sign_in" id="submit_sign_in" value="[% loc('Post') %]"> + <input class="green-btn js-submit_sign_in" type="submit" name="submit_sign_in" value="[% loc('Post') %]"> </div> <div class="checkbox-group"> diff --git a/templates/web/bromley/report/display.html b/templates/web/bromley/report/display.html index 073d0f6d6..e556098bf 100644 --- a/templates/web/bromley/report/display.html +++ b/templates/web/bromley/report/display.html @@ -102,7 +102,7 @@ [% INCLUDE name %] - <input class="final-submit green-btn" type="submit" id="update_post" value="[% loc('Post') %]"> + <input class="final-submit green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Post') %]"> [% ELSE %] @@ -132,7 +132,7 @@ <div class="form-txt-submit-box"> <input type="password" name="password_register" id="password_register" value="" placeholder="[% loc('Enter a password') %]"> - <input class="green-btn" type="submit" name="submit_register" id="submit_register" value="[% loc('Post') %]"> + <input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Post') %]"> </div> </div> <div id="form_sign_in_yes" class="form-box"> @@ -144,7 +144,7 @@ [% END %] <div class="form-txt-submit-box"> <input type="password" name="password_sign_in" id="password_sign_in" value="" placeholder="[% loc('Your password') %]"> - <input class="green-btn" type="submit" name="submit_sign_in" id="submit_sign_in" value="[% loc('Post') %]"> + <input class="green-btn js-submit_sign_in" type="submit" name="submit_sign_in" value="[% loc('Post') %]"> </div> <div class="checkbox-group"> @@ -176,13 +176,13 @@ [% IF field_errors.first_name %] <p class='form-error'>[% field_errors.first_name %]</p> [% END %] - <input type="text" value="[% names.first || first_name | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]"> + <input class="js-form-name" type="text" value="[% names.first || first_name | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]"> <label for="form_last_name">[% loc('Last Name') %]</label> [% IF field_errors.last_name %] <p class='form-error'>[% field_errors.last_name %]</p> [% END %] - <input type="text" value="[% names.last || last_name | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]"> + <input class="js-form-name" type="text" value="[% names.last || last_name | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]"> <div class="checkbox-group"> <input type="checkbox" name="may_show_name" id="form_may_show_name" value="1"[% ' checked' IF update AND NOT update.anonymous %]> diff --git a/templates/web/bromley/report/new/fill_in_details_form.html b/templates/web/bromley/report/new/fill_in_details_form.html index c25d836c6..d89e5d3d5 100644 --- a/templates/web/bromley/report/new/fill_in_details_form.html +++ b/templates/web/bromley/report/new/fill_in_details_form.html @@ -98,13 +98,13 @@ [% IF field_errors.first_name %] <p class='form-error'>[% field_errors.first_name %]</p> [% END %] - <input type="text" value="[% ( first_name || names.first ) | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]"> + <input class="js-form-name" type="text" value="[% ( first_name || names.first ) | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]"> <label for="form_last_name">[% loc('Last Name') %]</label> [% IF field_errors.last_name %] <p class='form-error'>[% field_errors.last_name %]</p> [% END %] - <input type="text" value="[% ( last_name || names.last ) | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]"> + <input class="js-form-name" type="text" value="[% ( last_name || names.last ) | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]"> [%# if there is nothing in the name field then set check box as default on form %] @@ -121,7 +121,7 @@ </div> <div class="form-txt-submit-box"> - <input class="green-btn" type="submit" id="submit_register" name="submit_register" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Submit') %]"> </div> </div> [% ELSE %] @@ -145,13 +145,13 @@ [% IF field_errors.first_name %] <p class='form-error'>[% field_errors.first_name %]</p> [% END %] - <input type="text" class="form-focus-trigger" value="[% first_name | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]"> + <input type="text" class="form-focus-trigger js-form-name" value="[% first_name | html %]" name="first_name" id="form_first_name" placeholder="[% loc('Your first name') %]"> <label for="form_last_name">[% loc('Last Name') %]</label> [% IF field_errors.last_name %] <p class='form-error'>[% field_errors.last_name %]</p> [% END %] - <input type="text" class="form-focus-trigger" value="[% last_name | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]"> + <input type="text" class="form-focus-trigger js-form-name" value="[% last_name | html %]" name="last_name" id="form_last_name" placeholder="[% loc('Your last name') %]"> [%# if there is nothing in the name field then set check box as default on form %] <div class="checkbox-group"> @@ -174,7 +174,7 @@ <div class="form-txt-submit-box form-focus-hidden"> <input type="password" name="password_register" id="password_register" value="" placeholder="[% loc('Enter a password') %]"> - <input class="green-btn" type="submit" id="submit_register" name="submit_register" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Submit') %]"> </div> </div> @@ -188,7 +188,7 @@ <p class='form-error'>[% field_errors.password %]</p> [% END %] <input type="password" name="password_sign_in" id="password_sign_in" placeholder="[% loc('Your password') %]" value=""> - <input class="green-btn" type="submit" id="submit_sign_in" name="submit_sign_in" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_sign_in" type="submit" name="submit_sign_in" value="[% loc('Submit') %]"> </div> <div class="checkbox-group"> diff --git a/templates/web/fixamingata/report/new/form_user_loggedout.html b/templates/web/fixamingata/report/new/form_user_loggedout.html index 36e7d95f4..c391ce75f 100644 --- a/templates/web/fixamingata/report/new/form_user_loggedout.html +++ b/templates/web/fixamingata/report/new/form_user_loggedout.html @@ -18,7 +18,7 @@ <p class='form-error'>[% field_errors.name %]</p> [% END %] - <input type="text" class="form-focus-trigger validName" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> + <input type="text" class="form-focus-trigger validName js-form-name" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> [%# if there is nothing in the name field then set check box as default on form %] <div class="checkbox-group"> @@ -41,7 +41,7 @@ <div class="form-txt-submit-box"> <input type="password" name="password_register" id="password_register" value="" placeholder="[% loc('Enter a password') %]"> - <input class="green-btn" type="submit" id="submit_register" name="submit_register" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Submit') %]"> </div> </div> <div id="form_sign_in_yes" class="form-box"> @@ -54,7 +54,7 @@ <p class='form-error'>[% field_errors.password %]</p> [% END %] <input type="password" name="password_sign_in" id="password_sign_in" placeholder="[% loc('Your password') %]" value=""> - <input class="green-btn" type="submit" id="submit_sign_in" name="submit_sign_in" value="[% loc('Submit') %]"> + <input class="green-btn js-submit_sign_in" type="submit" name="submit_sign_in" value="[% loc('Submit') %]"> </div> <div class="checkbox-group"> diff --git a/templates/web/fixmystreet.com/about/posters.html b/templates/web/fixmystreet.com/about/posters.html index 8a53cf1e2..1a9a4400c 100644 --- a/templates/web/fixmystreet.com/about/posters.html +++ b/templates/web/fixmystreet.com/about/posters.html @@ -85,7 +85,7 @@ <p class="badge-preview">[% badge %]</p> <p>Copy and paste the text below to add this badge to your site:</p> -<textarea class="badge-code" onclick="this.select()">[% badge | html %]</textarea> +<textarea class="badge-code js-click-select">[% badge | html %]</textarea> <p><small>(thanks to Lincolnshire Council for the image)</small></p> <h2 id="print">Printed Materials</h2> diff --git a/templates/web/fixmystreet.com/report/new/extra_name.html b/templates/web/fixmystreet.com/report/new/extra_name.html index 4663c025d..80ab1837a 100644 --- a/templates/web/fixmystreet.com/report/new/extra_name.html +++ b/templates/web/fixmystreet.com/report/new/extra_name.html @@ -30,7 +30,7 @@ shared with the council or displayed publicly.</em> [% title = '' %] [% IF fms_extra_title %][% title = fms_extra_title | upper %] [% ELSIF c.user && c.user.title %][% title = c.user.title | upper %][% END %] -<select class="form-focus-trigger required" id="form_fms_extra_title" +<select class="form-focus-trigger required js-form-name" id="form_fms_extra_title" name="fms_extra_title"> <option></option> <option value="MR"[% ' selected' IF title == 'MR' %]>Mr</option> diff --git a/templates/web/oxfordshire/header.html b/templates/web/oxfordshire/header.html index e347c8677..d5884272b 100644 --- a/templates/web/oxfordshire/header.html +++ b/templates/web/oxfordshire/header.html @@ -42,7 +42,7 @@ <[% IF c.req.uri.path == '/my' OR ( c.req.uri.path == '/auth' AND c.req.params.r == 'my' ) %]span[% ELSE %]a href="/my"[% END %]>[% c.user_exists ? loc("Your account") : loc("Sign in") %]</[% ( c.req.uri.path == '/my' OR ( c.req.uri.path == '/auth' AND c.req.params.r == 'my' ) ) ? 'span' : 'a' %]> </li> - [% IF c.user_exists AND c.user.has_permission_to('planned_reports', c.user.from_body.id) %] + [% IF c.user_exists AND c.user.has_body_permission_to('planned_reports') %] <li> <[% IF c.req.uri.path == '/my/planned' %]span[% ELSE %]a href="/my/planned"[% END %]>[% loc('Planned reports') %]</[% c.req.uri.path == '/my/planned' ? 'span' : 'a' %]> diff --git a/templates/web/oxfordshire/report/_main_sent_info.html b/templates/web/oxfordshire/report/_main_sent_info.html index c955a5fae..9865153d3 100644 --- a/templates/web/oxfordshire/report/_main_sent_info.html +++ b/templates/web/oxfordshire/report/_main_sent_info.html @@ -1,3 +1,4 @@ -[% IF problem.whensent %] - <p class="council_sent_info">[% problem.duration_string(c) %]</p> +[% SET duration_clause = problem.duration_string(c) %] +[% IF duration_clause %] + <p class="council_sent_info">[% duration_clause %]</p> [% END %] diff --git a/templates/web/seesomething/report/new/fill_in_details_form.html b/templates/web/seesomething/report/new/fill_in_details_form.html index fa1c5cbb2..54977f141 100644 --- a/templates/web/seesomething/report/new/fill_in_details_form.html +++ b/templates/web/seesomething/report/new/fill_in_details_form.html @@ -78,7 +78,7 @@ <p class='form-error'>[% field_errors.name %]</p> [% END %] - <input type="text" class="form-focus-trigger validName" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> + <input type="text" class="form-focus-trigger validName js-form-name" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> <label for="form_email">[% loc('Your email (optional)') %]</label> [% IF field_errors.email %] diff --git a/templates/web/zurich/footer.html b/templates/web/zurich/footer.html index 98c24964e..d299284d6 100644 --- a/templates/web/zurich/footer.html +++ b/templates/web/zurich/footer.html @@ -14,8 +14,9 @@ </p> [% END %] <ul class="nav-menu nav-menu--main mob-only"> - <li><[% IF c.req.uri.path == '/' %]a onclick="$('html, body').animate({scrollTop:0}, 500); return false;" href="#site-header"[% ELSE %]a href="/"[% END %] - >[% loc("Report a problem") %]</[% c.req.uri.path == '/' ? 'a' : 'a' %]></li>[% + <li><[% IF c.req.uri.path == '/' %]span[% ELSE %]a href="/"[% END %] + class="report-a-problem-btn" + >[% loc("Report a problem") %]</[% c.req.uri.path == '/' ? 'span' : 'a' %]></li>[% %]<li><[% IF c.req.uri.path == '/reports' %]span[% ELSE %]a href="/reports"[% END %]>[% loc("All reports") %]</[% c.req.uri.path == '/reports' ? 'span' : 'a' %]></li>[% %]<li><[% IF c.req.uri.path == '/faq' %]span[% ELSE %]a href="/faq"[% END diff --git a/templates/web/zurich/report/new/fill_in_details_form.html b/templates/web/zurich/report/new/fill_in_details_form.html index f7139fccd..9158fa090 100644 --- a/templates/web/zurich/report/new/fill_in_details_form.html +++ b/templates/web/zurich/report/new/fill_in_details_form.html @@ -60,7 +60,7 @@ [% IF field_errors.name %] <p class='form-error'>[% field_errors.name %]</p> [% END %] - <input type="text" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> + <input class="js-form-name" type="text" value="[% report.name | html %]" name="name" id="form_name" placeholder="[% loc('Your name') %]"> <label for="form_phone">[% loc('Phone number') %]</label> [% IF field_errors.phone %] @@ -69,8 +69,8 @@ <input type="text" value="[% report.user.phone | html %]" name="phone" id="form_phone" placeholder="[% loc('Your phone number') %]" required> <div class="form-txt-submit-box"> - [%# ID of submit_sign_in so name can be option, name of submit_register so it doesn't try and sign us in %] - <p><input class="green-btn" type="submit" id="submit_sign_in" name="submit_register" value="[% loc('Submit') %]"> + [%# class of submit_sign_in so name can be optional, name of submit_register so it doesn't try and sign us in %] + <p><input class="green-btn js-submit_sign_in" type="submit" name="submit_register" value="[% loc('Submit') %]"> </div> </div> diff --git a/web/cobrands/fixmystreet.com/posters.js b/web/cobrands/fixmystreet.com/posters.js index caf09fd0e..629ffb065 100644 --- a/web/cobrands/fixmystreet.com/posters.js +++ b/web/cobrands/fixmystreet.com/posters.js @@ -26,4 +26,5 @@ $.fn.link_track = function(eventCategory, eventAction, eventLabel) { $(function() { $("[data-goodielink]").link_track('goodie', 'download', 'goodielink'); + $('.js-click-select').on('click', function() { this.select(); }); }); diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index 50cbc53c5..b6f92b6d6 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -194,6 +194,10 @@ $.extend(fixmystreet.set_up, { // In case we've come here by clicking back to a form that disabled a submit button $('input[type=submit]').removeAttr('disabled'); + + $('[data-confirm]').on('click', function() { + return confirm(this.getAttribute('data-confirm')); + }); }, questionnaire: function() { @@ -217,7 +221,6 @@ $.extend(fixmystreet.set_up, { jQuery.validator.addMethod('validCategory', function(value, element) { return this.optional(element) || value != '-- Pick a category --'; }, translation_strings.category ); - var form_submitted = 0; var submitted = false; $("form.validate").each(function(){ @@ -228,27 +231,21 @@ $.extend(fixmystreet.set_up, { onfocusout: false, errorElement: 'div', errorClass: 'form-error', - // we do this to stop things jumping around on blur - success: function (err) { if ( form_submitted ) { err.addClass('label-valid').removeClass('label-valid-hidden').html( ' ' ); } else { err.addClass('label-valid-hidden'); } }, errorPlacement: function( error, element ) { - // Different for old/new style design - if ($('.form-field').length) { - element.parent('div.form-field').before( error ); - } else { - element.before( error ); - } + element.before( error ); }, submitHandler: function(form) { if (form.submit_problem) { $('input[type=submit]', form).prop("disabled", true); } - form.submit(); }, // make sure we can see the error message when we focus on invalid elements showErrors: function( errorMap, errorList ) { if ( submitted && errorList.length ) { - $(window).scrollTop( $(errorList[0].element).offset().top - 120 ); + var currScroll = $('#map_sidebar').scrollTop(), + pos = $(errorList[0].element).position().top; + $('#map_sidebar').scrollTop( currScroll + pos - 120 ); } this.defaultShowErrors(); submitted = false; @@ -257,43 +254,17 @@ $.extend(fixmystreet.set_up, { }); }); - $('input[type=submit]').click( function(e) { form_submitted = 1; } ); - /* set correct required status depending on what we submit * NB: need to add things to form_category as the JS updating * of this we do after a map click removes them */ - $('#submit_sign_in').click( function(e) { - $('#form_category').addClass('required validCategory').removeClass('valid'); - $('#form_name').removeClass(); - $('#form_first_name').removeClass(); - $('#form_last_name').removeClass(); - $('#form_fms_extra_title').removeClass(); - } ); - - $('#submit_register').click( function(e) { + $('.js-submit_sign_in').click( function(e) { $('#form_category').addClass('required validCategory').removeClass('valid'); - $('#form_name').addClass('required'); - if ( $('#mapForm').length ) { - $('#form_name').addClass('validName'); - } - $('#form_first_name').addClass('required'); - $('#form_last_name').addClass('required'); - $('#form_fms_extra_title').addClass('required'); + $('.js-form-name').removeClass('required'); } ); - $('#problem_submit > input[type="submit"]').click( function(e) { + $('.js-submit_register').click( function(e) { $('#form_category').addClass('required validCategory').removeClass('valid'); - $('#form_name').addClass('required'); - if ( $('#mapForm').length ) { - $('#form_name').addClass('validName'); - } - $('#form_first_name').addClass('required'); - $('#form_last_name').addClass('required'); - $('#form_fms_extra_title').addClass('required'); - } ); - - $('#update_post').click( function(e) { - $('#form_name').addClass('required').removeClass('valid'); + $('.js-form-name').addClass('required'); } ); $('#facebook_sign_in, #twitter_sign_in').click(function(e){ @@ -415,12 +386,6 @@ $.extend(fixmystreet.set_up, { }); }, - add_validation: function() { - // Map form doesn't work in some browsers with HTML5 validation and hidden form, so - // we disable validation by default, and add it in the JS case. - $('#mapForm').removeAttr('novalidate'); - }, - contribute_as: function() { $('.content').on('change', '.js-contribute-as', function(){ var opt = this.options[this.selectedIndex], @@ -862,6 +827,13 @@ $.extend(fixmystreet.set_up, { } add_handlers( $('.problem-header'), 'problem' ); add_handlers( $('.item-list__item--updates'), 'update' ); + }, + + response_templates: function() { + $('.js-template-name').change(function() { + var $this = $(this); + $('#' + $this.data('for')).val($this.val()); + }); } }); @@ -1085,6 +1057,7 @@ fixmystreet.display = { fixmystreet.set_up.dropzone($sideReport); fixmystreet.set_up.form_focus_triggers(); fixmystreet.set_up.moderation(); + fixmystreet.set_up.response_templates(); window.selected_problem_id = reportId; var marker = fixmystreet.maps.get_marker_by_id(reportId); diff --git a/web/cobrands/oxfordshire/layout.scss b/web/cobrands/oxfordshire/layout.scss index c9783b14d..7417b7081 100644 --- a/web/cobrands/oxfordshire/layout.scss +++ b/web/cobrands/oxfordshire/layout.scss @@ -62,7 +62,7 @@ body.twothirdswidthpage { // To prevent font size larger interfering with the fixed Oxfordshire layout .container { width: auto; } -.full-width { width: 464px; } +body:not(.admin) .full-width { width: 464px; } .shadow-wrap { width: 464px; } .content { width: 432px; } diff --git a/web/cobrands/sass/_base.scss b/web/cobrands/sass/_base.scss index 576538daa..d1fdec343 100644 --- a/web/cobrands/sass/_base.scss +++ b/web/cobrands/sass/_base.scss @@ -458,15 +458,6 @@ ul.error { @include border-radius(0.25em); } -// don't display valid error boxes as now the page jump -// won't be until the user submits, which is fine -div.label-valid, -p.label-valid { - display:none !important; - visibility: hidden; -} - - /*** LAYOUT ***/ diff --git a/web/iphone/.gitignore b/web/iphone/.gitignore deleted file mode 100644 index 973f53659..000000000 --- a/web/iphone/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/_Inline diff --git a/web/iphone/iphone-1start.png b/web/iphone/iphone-1start.png Binary files differdeleted file mode 100644 index 1d804af8d..000000000 --- a/web/iphone/iphone-1start.png +++ /dev/null diff --git a/web/iphone/iphone-2locfound.png b/web/iphone/iphone-2locfound.png Binary files differdeleted file mode 100644 index bade44fd9..000000000 --- a/web/iphone/iphone-2locfound.png +++ /dev/null diff --git a/web/iphone/iphone-3picture.png b/web/iphone/iphone-3picture.png Binary files differdeleted file mode 100644 index 3bcab408a..000000000 --- a/web/iphone/iphone-3picture.png +++ /dev/null diff --git a/web/iphone/iphone-4subject.png b/web/iphone/iphone-4subject.png Binary files differdeleted file mode 100644 index cd1588b30..000000000 --- a/web/iphone/iphone-4subject.png +++ /dev/null diff --git a/web/iphone/iphone-5details.png b/web/iphone/iphone-5details.png Binary files differdeleted file mode 100644 index c05ec1626..000000000 --- a/web/iphone/iphone-5details.png +++ /dev/null diff --git a/web/iphone/iphone-6emailkeyboard.png b/web/iphone/iphone-6emailkeyboard.png Binary files differdeleted file mode 100644 index 32c7f690f..000000000 --- a/web/iphone/iphone-6emailkeyboard.png +++ /dev/null diff --git a/web/iphone/iphone-7uploading.png b/web/iphone/iphone-7uploading.png Binary files differdeleted file mode 100644 index 05bfde053..000000000 --- a/web/iphone/iphone-7uploading.png +++ /dev/null diff --git a/web/iphone/iphone-8response.png b/web/iphone/iphone-8response.png Binary files differdeleted file mode 100644 index a6a25bcbd..000000000 --- a/web/iphone/iphone-8response.png +++ /dev/null diff --git a/web/iphone/iphone-9about.png b/web/iphone/iphone-9about.png Binary files differdeleted file mode 100644 index b80f1972b..000000000 --- a/web/iphone/iphone-9about.png +++ /dev/null diff --git a/web/iphone/iphone-allready.png b/web/iphone/iphone-allready.png Binary files differdeleted file mode 100644 index ae193feb1..000000000 --- a/web/iphone/iphone-allready.png +++ /dev/null diff --git a/web/iphone/iphone-contactphoto.png b/web/iphone/iphone-contactphoto.png Binary files differdeleted file mode 100644 index 440511138..000000000 --- a/web/iphone/iphone-contactphoto.png +++ /dev/null diff --git a/web/iphone/iphone-detailsdone.png b/web/iphone/iphone-detailsdone.png Binary files differdeleted file mode 100644 index c7de03578..000000000 --- a/web/iphone/iphone-detailsdone.png +++ /dev/null diff --git a/web/iphone/iphone-editname.png b/web/iphone/iphone-editname.png Binary files differdeleted file mode 100644 index 5807235d3..000000000 --- a/web/iphone/iphone-editname.png +++ /dev/null diff --git a/web/iphone/iphone-editsummary.png b/web/iphone/iphone-editsummary.png Binary files differdeleted file mode 100644 index 251fad6df..000000000 --- a/web/iphone/iphone-editsummary.png +++ /dev/null diff --git a/web/iphone/iphone-editsummary2.png b/web/iphone/iphone-editsummary2.png Binary files differdeleted file mode 100644 index 7019071c4..000000000 --- a/web/iphone/iphone-editsummary2.png +++ /dev/null diff --git a/web/iphone/iphone-pickpicture1.png b/web/iphone/iphone-pickpicture1.png Binary files differdeleted file mode 100644 index 8f55bff93..000000000 --- a/web/iphone/iphone-pickpicture1.png +++ /dev/null diff --git a/web/iphone/iphone-pickpicture2.png b/web/iphone/iphone-pickpicture2.png Binary files differdeleted file mode 100644 index 582673abd..000000000 --- a/web/iphone/iphone-pickpicture2.png +++ /dev/null diff --git a/web/iphone/iphone-pickpicture3.png b/web/iphone/iphone-pickpicture3.png Binary files differdeleted file mode 100644 index e7960798f..000000000 --- a/web/iphone/iphone-pickpicture3.png +++ /dev/null |