diff options
30 files changed, 406 insertions, 338 deletions
diff --git a/bin/update-schema b/bin/update-schema index 500e771f1..479a55c8e 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 '0047' if column_exists('response_priorities', 'description'); return '0046' if column_exists('users', 'extra'); return '0045' if table_exists('response_priorities'); return '0044' if table_exists('contact_response_templates'); diff --git a/bin/zurich/overdue-alert b/bin/zurich/overdue-alert index 3b312c4db..90e31df1c 100755 --- a/bin/zurich/overdue-alert +++ b/bin/zurich/overdue-alert @@ -49,7 +49,8 @@ sub loop_through { my %to_send = (); while (my $row = $reports->next) { - $to_send{$row->bodies_str} .= '* ' . $row->id . ": '" . $row->title . "'\n\n"; + $to_send{$row->bodies_str} ||= []; + push @{$to_send{$row->bodies_str}}, $row; } foreach my $body_id (keys %to_send) { @@ -66,6 +67,7 @@ sub send_alert { my $h = { data => $data, admin_url => $cobrand->admin_base_url, + cobrand => $cobrand, }; my $to = [ [ $body_email, $body->name ] ]; diff --git a/db/downgrade_0047---0046.sql b/db/downgrade_0047---0046.sql new file mode 100644 index 000000000..2f07c44ea --- /dev/null +++ b/db/downgrade_0047---0046.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE response_priorities + DROP COLUMN description; + +COMMIT; diff --git a/db/schema.sql b/db/schema.sql index fe45fb4aa..d3bb5040e 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -134,6 +134,7 @@ CREATE TABLE response_priorities ( body_id int references body(id) not null, deleted boolean not null default 'f', name text not null, + description text, unique(body_id, name) ); diff --git a/db/schema_0047-response-priorities-add-description.sql b/db/schema_0047-response-priorities-add-description.sql new file mode 100644 index 000000000..1aa856d75 --- /dev/null +++ b/db/schema_0047-response-priorities-add-description.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE response_priorities + ADD COLUMN description TEXT; + +COMMIT; diff --git a/perllib/FixMyStreet/App/Controller/Admin/ResponsePriorities.pm b/perllib/FixMyStreet/App/Controller/Admin/ResponsePriorities.pm index ce17390d9..032e593c6 100644 --- a/perllib/FixMyStreet/App/Controller/Admin/ResponsePriorities.pm +++ b/perllib/FixMyStreet/App/Controller/Admin/ResponsePriorities.pm @@ -69,6 +69,7 @@ sub edit : Path : Args(2) { if ($c->req->method eq 'POST') { $priority->deleted( $c->get_param('deleted') ? 1 : 0 ); $priority->name( $c->get_param('name') ); + $priority->description( $c->get_param('description') ); $priority->update_or_insert; my @live_contact_ids = map { $_->id } @live_contacts; diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index 855732f83..69dc17e44 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -658,13 +658,15 @@ order of title. =cut sub response_templates { - my $problem = shift; - return $problem->result_source->schema->resultset('ResponseTemplate')->search( + my $self = shift; + return $self->result_source->schema->resultset('ResponseTemplate')->search( { - body_id => $problem->bodies_str_ids + 'me.body_id' => $self->bodies_str_ids, + 'contact.category' => [ $self->category, undef ], }, { - order_by => 'title' + order_by => 'title', + join => { 'contact_response_templates' => 'contact' }, } ); } @@ -681,7 +683,7 @@ sub response_priorities { return $self->result_source->schema->resultset('ResponsePriority')->search( { 'me.body_id' => $self->bodies_str_ids, - 'contact.category' => $self->category, + 'contact.category' => [ $self->category, undef ], }, { order_by => 'name', diff --git a/perllib/FixMyStreet/DB/Result/ResponsePriority.pm b/perllib/FixMyStreet/DB/Result/ResponsePriority.pm index d312fbcea..6bc8474fa 100644 --- a/perllib/FixMyStreet/DB/Result/ResponsePriority.pm +++ b/perllib/FixMyStreet/DB/Result/ResponsePriority.pm @@ -24,6 +24,8 @@ __PACKAGE__->add_columns( { data_type => "text", is_nullable => 0 }, "deleted", { data_type => "boolean", default_value => \"false", is_nullable => 0 }, + "description", + { data_type => "text", is_nullable => 1 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("response_priorities_body_id_name_key", ["body_id", "name"]); @@ -47,8 +49,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-09-07 11:01:40 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:B1swGtQzC3qRa0LUM4IyzA +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-10-17 16:37:28 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:wok3cPA7cPjG4e9lnc1PIg __PACKAGE__->many_to_many( contacts => 'contact_response_priorities', 'contact' ); diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t index 7ba84b652..a0e013459 100644 --- a/t/app/controller/admin.t +++ b/t/app/controller/admin.t @@ -1453,6 +1453,7 @@ subtest "response priorities can be added" => sub { my $fields = { name => "Cat 1A", + description => "Fixed within 24 hours", deleted => undef, "contacts[".$oxfordshirecontact->id."]" => 1, }; @@ -1466,6 +1467,7 @@ subtest "response priorities can be listed" => sub { $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id ); $mech->content_contains( $oxfordshire->response_priorities->first->name ); + $mech->content_contains( $oxfordshire->response_priorities->first->description ); }; subtest "response priorities are limited by body" => sub { diff --git a/t/app/model/problem.t b/t/app/model/problem.t index 836e8a047..bd7d0e55c 100644 --- a/t/app/model/problem.t +++ b/t/app/model/problem.t @@ -749,6 +749,20 @@ subtest 'check reports from abuser not sent' => sub { ok $abuse->delete(), 'user removed from abuse table'; }; +subtest 'check response templates' => sub { + my $c1 = $mech->create_contact_ok(category => 'Potholes', body_id => $body_ids{2651}, email => 'p'); + my $c2 = $mech->create_contact_ok(category => 'Graffiti', body_id => $body_ids{2651}, email => 'g'); + my $t1 = FixMyStreet::DB->resultset('ResponseTemplate')->create({ body_id => $body_ids{2651}, title => "Title 1", text => "Text 1" }); + my $t2 = FixMyStreet::DB->resultset('ResponseTemplate')->create({ body_id => $body_ids{2651}, title => "Title 2", text => "Text 2" }); + my $t3 = FixMyStreet::DB->resultset('ResponseTemplate')->create({ body_id => $body_ids{2651}, title => "Title 3", text => "Text 3" }); + $t1->add_to_contacts($c1); + $t2->add_to_contacts($c2); + my ($problem) = $mech->create_problems_for_body(1, $body_ids{2651}, 'TITLE'); + is $problem->response_templates, 1, 'Only the global template returned'; + ($problem) = $mech->create_problems_for_body(1, $body_ids{2651}, 'TITLE', { category => 'Potholes' }); + is $problem->response_templates, 2, 'Global and pothole templates returned'; +}; + END { $problem->comments->delete if $problem; $problem->delete if $problem; diff --git a/templates/web/base/admin/body-form.html b/templates/web/base/admin/body-form.html index 6dd8a9547..b1f4bce2c 100644 --- a/templates/web/base/admin/body-form.html +++ b/templates/web/base/admin/body-form.html @@ -113,115 +113,7 @@ </select> </p> - <div class="admin-open311-only"> - <p class="fms-admin-info"> - [% loc( - "These settings are for bodies that use Open311 (or other back-end integration) to receive problem reports.<br> - <strong>You don't need to set them if the Send Method is email.</strong>. - For more information on Open311, see - <a href='https://www.mysociety.org/2013/01/17/open311-explained/' class='admin-offsite-link'>this article</a>. - " - ) %] - </p> - - <div class="admin-hint"> - <p> - [% loc( - "The <strong>endpoint</strong> is the URL of the service that FixMyStreet will connect to - when sending reports to this body." - ) %] - </p> - </div> - <p> - <label for="endpoint">[% loc('Endpoint') %]</label> - <input type="text" class="form-control" name="endpoint" id="endpoint" value="[% body.endpoint | html %]" size="50"> - </p> - - <div class="admin-hint"> - <p> - [% loc( - "The <strong>jurisdiction</strong> is only needed if the endpoint is serving more - than one. If the body is running its own endpoint, you can usually leave this blank." - ) %] - </p> - </div> - <p> - <label for="jurisdiction">Open311 Jurisdiction</label> - <input type="text" class="form-control" name="jurisdiction" id="jurisdiction" value="[% body.jurisdiction | html %]" size="50"> - </p> - - <div class="admin-hint"> - <p> - [% loc( - "Some endpoints require an <strong>API key</strong> to indicate that the reports are being - sent from your FixMyStreet installation." - ) %] - </p> - </div> - <p> - <label for="api_key">Open311 API Key</label> - <input type="text" class="form-control" name="api_key" id="api_key" value="[% body.api_key | html %]" size="25"> - </p> - - <div class="admin-hint"> - <p> - [% loc( - "Enable <strong>Open311 update-sending</strong> if the endpoint will send and receive - updates to existing reports. If you're not sure, it probably does not, so leave this unchecked. - For more information, see - <a href='https://www.mysociety.org/2013/02/20/open311-extended/' class='admin-offsite-link'>this article</a>." - ) %] - </p> - </div> - <p> - <input type="checkbox" id="send_comments" name="send_comments"[% ' checked' IF body.send_comments %]> - <label for="send_comments" class="inline">Use Open311 update-sending extension</label> - </p> - - <div class="admin-hint"> - <p> - [% loc( - "If you've enabled Open311 update-sending above, you must identify which - FixMyStreet <strong>user</strong> will be attributed as the creator of those updates - when they are shown on the site. Enter the ID (number) of that user." - ) %] - </p> - </div> - <p> - <label for"comment_user_id">User ID to attribute fetched comments to</label> - <input type="text" class="form-control" name="comment_user_id" value="[% body.comment_user_id %]"> - [% IF body.comment_user_id %] - <a href="[% c.uri_for('user_edit', body.comment_user_id) %]">[% loc('edit user') %]</a> - [% END %] - </p> - - <div class="admin-hint"> - <p> - [% loc( - "If you've enabled Open311 update-sending above, enable <strong>suppression of alerts</strong> - if you do <strong>not</strong> want that user to be notified whenever these updates are created." - ) %] - </p> - </div> - <p> - <input type="checkbox" id="suppress_alerts" name="suppress_alerts"[% ' checked' IF body.suppress_alerts %]> - <label for="suppress_alerts" class="inline">Do not send email alerts on fetched comments to problem creator</label> - </p> - - <div class="admin-hint"> - <p> - [% loc( - "If you've enabled Open311 update-sending above, Open311 usually only accepts OPEN or CLOSED status in - its updates. Enable <strong>extended Open311 stauses</strong> if you want to allow extra states to be passed. - Check that your cobrand supports this feature before switching it on." - ) %] - </p> - </div> - <p> - <input type="checkbox" id="send_extended_statuses" name="send_extended_statuses"[% ' checked' IF body.send_extended_statuses %]> - <label for="send_extended_statuses" class="inline">Send extended Open311 statuses with service request updates</label> - </p> - </div> + [% INCLUDE 'admin/open311-form-fields.html', object = body, show_body_fields = 1 %] <div class="admin-hint"> <p> diff --git a/templates/web/base/admin/body.html b/templates/web/base/admin/body.html index 52df20c89..0b8d3b18c 100644 --- a/templates/web/base/admin/body.html +++ b/templates/web/base/admin/body.html @@ -120,111 +120,13 @@ <h2>[% loc('Add new category') %]</h2> [% END %] -[% IF errors %] -<div class="fms-admin-warning"> - [% errors.values.join('<br>') %] -</div> -[% END %] + [% IF errors %] + <div class="fms-admin-warning"> + [% errors.values.join('<br>') %] + </div> + [% END %] - <form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - - <div class="admin-hint"> - <p> - [% loc('Choose a <strong>category</strong> name that makes sense to the public (e.g., "Pothole", "Street lighting") but is helpful - to the body too. These will appear in the drop-down menu on the report-a-problem page.') %] - <br> - [% loc("If two or more bodies serve the same location, FixMyStreet combines identical categories into a single entry in - the menu. Make sure you use the same category name in the bodies if you want this to happen.") %] - </p> - </div> - <p> - <strong>[% loc('Category:') %] </strong><input type="text" class="form-control" name="category" size="30" value="[% contact.category | html %]"> - </p> - - <div class="admin-hint"> - <p> - [% loc("The <strong>email address</strong> is the destination to which reports about this category will be sent. - Other categories for this body may have the same email address.") %] - </p> - [% IF (body.send_method AND body.send_method != 'Email') OR body.can_be_devolved %] - <p> - [% loc("If you're using <strong>a send method that is not email</strong>, enter the service ID (Open311) or equivalent identifier here.") %] - </p> - [% END %] - </div> - - <p> - <strong>[% loc('Email address:') %] </strong><input type="text" class="form-control" name="email" size="30" value="[% contact.email | html %]"> - </p> - - <div class="admin-hint"> - <p> - [% loc("Check <strong>confirmed</strong> to indicate that this contact has been confirmed as correct. - If you are not sure of the origin or validity of the contact, leave this unchecked.") %] - </p> - </div> - <p> - <input type="checkbox" name="confirmed" value="1" id="confirmed"[% ' checked' IF contact.confirmed OR contact.confirmed == "" %]> - <label for="confirmed" class="inline">[% loc('Confirmed') %]</label> - </p> - - <div class="admin-hint"> - <p> - [% loc("Check <strong>deleted</strong> to remove the category from use. - It will not appear as an available category in the drop-down menu on the report-a-problem page.") %] - </p> - </div> - <p> - <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> - <label for="deleted" class="inline">[% loc('Deleted') %]</label> - </p> - - <div class="admin-hint"> - <p> - [% loc("Use the <strong>note</strong> to record details that are only displayed in the admin. Notes are not shown publicly, and are not sent to the body.") %] - </p> - </div> - <p> - <strong>[% loc('Note:') %] </strong> <textarea class="form-control" name="note" rows="3" cols="40"></textarea> - </p> - - <div class="admin-hint"> - <p> - [% loc("Check <strong>private</strong> if reports in this category should <strong>never be displayed on the website</strong>. - <br> - Normally, categories are not private. - <br> - This is suitable for issues that you want to allow users to report to the body, but for which there is no public - interest in displaying the report. In the UK, we've used this for services like requesting an extra rubbish bin - at a specific address.") %] - </p> - </div> - <p> - <input type="checkbox" name="non_public" value="1" id="non_public" [% ' checked' IF contact.non_public %]> - <label for="non_public" class="inline">[% loc('Private') %]</label> - </p> - - <div class="admin-hint"> - <p> - [% loc("Check <strong>inspection required</strong> if reports in this category <strong>must be inspected</strong> before being sent.") %] - </p> - </div> - <p> - <input type="checkbox" name="inspection_required" value="1" id="inspection_required" [% 'checked' IF contact.get_extra_metadata('inspection_required') %]> - <label for="inspection_required" class="inline">[% loc('Inspection required') %]</label> - </p> - - <p> - <input type="hidden" name="posted" value="new" > - <input type="hidden" name="token" value="[% csrf_token %]" > - <input type="submit" class="btn" name="Create category" value="[% errors ? loc('Save changes') : loc('Create category') %]" > - </p> - - <div> - <input type="hidden" name=".cgifields" value="confirmed" > - <input type="hidden" name=".cgifields" value="deleted" > - </div> - </form> + [% INCLUDE 'admin/contact-form.html' %] </div> [% IF NOT errors and c.user.is_superuser %] diff --git a/templates/web/base/admin/category-checkboxes.html b/templates/web/base/admin/category-checkboxes.html new file mode 100644 index 000000000..63acd4112 --- /dev/null +++ b/templates/web/base/admin/category-checkboxes.html @@ -0,0 +1,18 @@ + <p> + <strong>[% loc('Categories:') %]</strong> + </p> + <ul> + <li> + [% loc('Select:') %] + <a href="#" data-select-all>[% loc('all') %]</a> / + <a href="#" data-select-none>[% loc('none') %]</a> + </li> + [% FOR contact IN contacts %] + <li> + <label> + <input type="checkbox" name="contacts[[% contact.id %]]" [% 'checked' IF contact.active %]/> + [% contact.category %] + </label> + </li> + [% END %] + </ul> diff --git a/templates/web/base/admin/category_edit.html b/templates/web/base/admin/category_edit.html index ebaa495db..d1a323819 100644 --- a/templates/web/base/admin/category_edit.html +++ b/templates/web/base/admin/category_edit.html @@ -19,78 +19,7 @@ [% END %] </p> -<form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8" id="category_edit"> - <p><strong>[% loc('Category:') %] </strong>[% contact.category | html %] - <input type="hidden" name="category" value="[% contact.category | html %]" > - <input type="hidden" name="token" value="[% csrf_token %]" > - - <p><strong>[% loc('Email:') %] </strong> - <input type="text" class="form-control" name="email" value="[% contact.email | html %]" size="30"> - - <p> - [% IF c.cobrand.moniker != 'zurich' %] - <input type="checkbox" name="confirmed" value="1" id="confirmed"[% ' checked' IF contact.confirmed %]> - <label class="inline" for="confirmed">[% loc('Confirmed' ) %]</label> - [% ELSE %] - <input type="hidden" name="confirmed" value="1"> - [% END %] - <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> - <label class="inline" for="deleted">[% loc('Deleted') %]</label> - [% IF c.cobrand.moniker != 'zurich' %] - <input type="checkbox" name="non_public" value="1" id="non_public"[% ' checked' IF contact.non_public %]> - <label class="inline" for="non_public">[% loc('Private') %]</label> - <input type="checkbox" name="inspection_required" value="1" id="inspection_required"[% ' checked' IF contact.get_extra_metadata('inspection_required') %]> - <label class="inline" for="inspection_required">[% loc('Inspection required') %]</label> - [% ELSE %] - <input type="checkbox" name="photo_required" value="1" id="photo_required"[% ' checked' IF contact.get_extra_metadata('photo_required') %]> - <label class="inline" for="photo_required">[% loc('Photo required') %]</label> - [% END %] - </p> - - [% IF c.cobrand.moniker != 'zurich' %] - <p [% 'class=hidden' UNLESS contact.get_extra_metadata('inspection_required') %]> - <label> - [% loc('Reputation threshold:') %] - <input type="text" class="form-control" name="reputation_threshold" id="reputation_threshold" - value="[% contact.get_extra_metadata('reputation_threshold') | html %]" size="30"> - </label> - </p> - [% END %] - - <p><strong>[% loc('Note:') %] </strong><textarea class="form-control" name="note" rows="3" cols="40"></textarea> - - [% IF body.can_be_devolved %] - <h2>[% loc('Configure Endpoint') %]</h2> - <form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <p> - <label for="endpoint">Endpoint</label> - <input type="text" class="form-control" name="endpoint" id="endpoint" value="[% contact.endpoint | html %]" size="50"> - </p> - - <p> - <label for="jurisdiction">Jurisdiction</label> - <input type="text" class="form-control" name="jurisdiction" id="jurisdiction" value="[% contact.jurisdiction | html %]" size="50"> - </p> - - <p> - <label for="api_key">Api Key</label> - <input type="text" class="form-control" name="api_key" id="api_key" value="[% contact.api_key | html %]" size="25"> - </p> - - <p> - <label for="send_method">Send Method</label> - <select class="form-control" name="send_method"> - <option value=""> -- Select a method -- </option> - [% FOR method IN send_methods %] - <option value="[% method %]"[% ' selected' IF contact.send_method == method %]>[% method %]</option> - [% END %] - </select> - </p> - [% END %] - - <input type="hidden" name="posted" value="new"> - <p><input type="submit" class="btn" name="Save changes" value="[% loc('Save changes') %]"> -</form> +[% INCLUDE 'admin/contact-form.html' %] [% IF contact.extra %] <h2>[% loc('Extra data:') %] </h2> diff --git a/templates/web/base/admin/contact-form.html b/templates/web/base/admin/contact-form.html new file mode 100644 index 000000000..83f634188 --- /dev/null +++ b/templates/web/base/admin/contact-form.html @@ -0,0 +1,139 @@ +<form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8" id="category_edit"> + + [% IF contact.in_storage %] + <p> + <h1>[% contact.category | html %]</h2> + <input type="hidden" name="category" value="[% contact.category | html %]" > + </p> + [% ELSE %] + <div class="admin-hint"> + <p> + [% loc('Choose a <strong>category</strong> name that makes sense to the public (e.g., "Pothole", "Street lighting") but is helpful + to the body too. These will appear in the drop-down menu on the report-a-problem page.') %] + <br> + [% loc("If two or more bodies serve the same location, FixMyStreet combines identical categories into a single entry in + the menu. Make sure you use the same category name in the bodies if you want this to happen.") %] + </p> + </div> + <p> + <strong>[% loc('Category') %] </strong><input type="text" class="form-control" name="category" size="30" value="[% contact.category | html %]" required> + </p> + [% END %] + + <div class="admin-hint"> + <p> + [% loc("The <strong>email address</strong> is the destination to which reports about this category will be sent. + Other categories for this body may have the same email address.") %] + </p> + [% IF (body.send_method AND body.send_method != 'Email') OR body.can_be_devolved %] + <p> + [% loc("If you're using <strong>a send method that is not email</strong>, enter the service ID (Open311) or equivalent identifier here.") %] + </p> + [% END %] + </div> + + <p> + <strong>[% loc('Email address') %] </strong><input type="text" class="form-control" name="email" size="30" value="[% contact.email | html %]" required> + </p> + + <div class="admin-hint"> + <p> + [% loc("Check <strong>confirmed</strong> to indicate that this contact has been confirmed as correct. + If you are not sure of the origin or validity of the contact, leave this unchecked.") %] + </p> + </div> + <p> + <input type="checkbox" name="confirmed" value="1" id="confirmed"[% ' checked' IF contact.confirmed OR contact.confirmed == "" %]> + <label for="confirmed" class="inline">[% loc('Confirmed') %]</label> + </p> + + <div class="admin-hint"> + <p> + [% loc("Check <strong>deleted</strong> to remove the category from use. + It will not appear as an available category in the drop-down menu on the report-a-problem page.") %] + </p> + </div> + <p> + <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> + <label for="deleted" class="inline">[% loc('Deleted') %]</label> + </p> + + <div class="admin-hint"> + <p> + [% loc("Check <strong>private</strong> if reports in this category should <strong>never be displayed on the website</strong>. + <br> + Normally, categories are not private. + <br> + This is suitable for issues that you want to allow users to report to the body, but for which there is no public + interest in displaying the report. In the UK, we've used this for services like requesting an extra rubbish bin + at a specific address.") %] + </p> + </div> + <p> + <input type="checkbox" name="non_public" value="1" id="non_public" [% ' checked' IF contact.non_public %]> + <label for="non_public" class="inline">[% loc('Private') %]</label> + </p> + + <div class="admin-hint"> + <p> + [% loc("Check <strong>inspection required</strong> if reports in this category <strong>must be inspected</strong> before being sent.") %] + </p> + </div> + <p> + <input type="checkbox" name="inspection_required" value="1" id="inspection_required" [% 'checked' IF contact.get_extra_metadata('inspection_required') %]> + <label for="inspection_required" class="inline">[% loc('Inspection required') %]</label> + </p> + + <div class="admin-hint [% 'hidden' UNLESS contact.get_extra_metadata('inspection_required') %]"> + <p> + [% loc("Reports will automatically be sent without needing to be inspected if the user's <strong>reputation</strong> is at or above this value. Set to <strong>0</strong> if all reports must be inspected regardless.") %] + </p> + </div> + <p [% 'class=hidden' UNLESS contact.get_extra_metadata('inspection_required') %]> + <label> + [% loc('Reputation threshold') %] + <input type="text" class="form-control" name="reputation_threshold" id="reputation_threshold" + value="[% contact.get_extra_metadata('reputation_threshold') | html %]" size="30"> + </label> + </p> + + [% IF body.can_be_devolved %] + <div class="admin-hint"> + <p> + [% loc( + "The <strong>send method</strong> determines how problem reports will be sent to the body. + If you leave this blank, <strong>send method defaults to email</strong>." + ) %] + </p> + </div> + <p> + <label for="send_method">Send Method</label> + <select class="form-control" name="send_method" id="send_method"> + <option value=""> -- Select a method -- </option> + [% FOR method IN send_methods %] + <option value="[% method %]"[% ' selected' IF contact.send_method == method %]>[% method %]</option> + [% END %] + </select> + </p> + + [% INCLUDE 'admin/open311-form-fields.html', object = contact%] + [% END %] + + <div class="admin-hint"> + <p> + [% loc("Use this field to record details that are only displayed in the admin. Input is not shown publicly, and is not sent to the body.") %] + </p> + </div> + <p> + <label> + [% loc('Summarise your changes') %] + <input class="form-control" type="text" name="note" size="30" required> + </label> + </p> + + <p> + <input type="hidden" name="posted" value="new" > + <input type="hidden" name="token" value="[% csrf_token %]" > + <input type="submit" class="btn" name="Create category" value="[% contact.in_storage ? loc('Save changes') : loc('Create category') %]" > + </p> +</form> diff --git a/templates/web/base/admin/open311-form-fields.html b/templates/web/base/admin/open311-form-fields.html new file mode 100644 index 000000000..008853b0b --- /dev/null +++ b/templates/web/base/admin/open311-form-fields.html @@ -0,0 +1,112 @@ +<div class="admin-open311-only"> + <p class="fms-admin-info"> + [% loc( + "These settings are for bodies that use Open311 (or other back-end integration) to receive problem reports.<br> + <strong>You don't need to set them if the Send Method is email.</strong>. + For more information on Open311, see + <a href='https://www.mysociety.org/2013/01/17/open311-explained/' class='admin-offsite-link'>this article</a>. + " + ) %] + </p> + + <div class="admin-hint"> + <p> + [% loc( + "The <strong>endpoint</strong> is the URL of the service that FixMyStreet will connect to + when sending reports to this body." + ) %] + </p> + </div> + <p> + <label for="endpoint">[% loc('Endpoint') %]</label> + <input type="text" class="form-control" name="endpoint" id="endpoint" value="[% object.endpoint | html %]" size="50"> + </p> + + <div class="admin-hint"> + <p> + [% loc( + "The <strong>jurisdiction</strong> is only needed if the endpoint is serving more + than one. If the body is running its own endpoint, you can usually leave this blank." + ) %] + </p> + </div> + <p> + <label for="jurisdiction">Open311 Jurisdiction</label> + <input type="text" class="form-control" name="jurisdiction" id="jurisdiction" value="[% object.jurisdiction | html %]" size="50"> + </p> + + <div class="admin-hint"> + <p> + [% loc( + "Some endpoints require an <strong>API key</strong> to indicate that the reports are being + sent from your FixMyStreet installation." + ) %] + </p> + </div> + <p> + <label for="api_key">Open311 API Key</label> + <input type="text" class="form-control" name="api_key" id="api_key" value="[% object.api_key | html %]" size="25"> + </p> + + [% IF show_body_fields %] + [%# These fields aren't shown for contacts %] + <div class="admin-hint"> + <p> + [% loc( + "Enable <strong>Open311 update-sending</strong> if the endpoint will send and receive + updates to existing reports. If you're not sure, it probably does not, so leave this unchecked. + For more information, see + <a href='https://www.mysociety.org/2013/02/20/open311-extended/' class='admin-offsite-link'>this article</a>." + ) %] + </p> + </div> + <p> + <input type="checkbox" id="send_comments" name="send_comments"[% ' checked' IF object.send_comments %]> + <label for="send_comments" class="inline">Use Open311 update-sending extension</label> + </p> + + <div class="admin-hint"> + <p> + [% loc( + "If you've enabled Open311 update-sending above, you must identify which + FixMyStreet <strong>user</strong> will be attributed as the creator of those updates + when they are shown on the site. Enter the ID (number) of that user." + ) %] + </p> + </div> + <p> + <label for"comment_user_id">User ID to attribute fetched comments to</label> + <input type="text" class="form-control" name="comment_user_id" value="[% object.comment_user_id %]"> + [% IF object.comment_user_id %] + <a href="[% c.uri_for('user_edit', object.comment_user_id) %]">[% loc('edit user') %]</a> + [% END %] + </p> + + <div class="admin-hint"> + <p> + [% loc( + "If you've enabled Open311 update-sending above, enable <strong>suppression of alerts</strong> + if you do <strong>not</strong> want that user to be notified whenever these updates are created." + ) %] + </p> + </div> + <p> + <input type="checkbox" id="suppress_alerts" name="suppress_alerts"[% ' checked' IF object.suppress_alerts %]> + <label for="suppress_alerts" class="inline">Do not send email alerts on fetched comments to problem creator</label> + </p> + + <div class="admin-hint"> + <p> + [% loc( + "If you've enabled Open311 update-sending above, Open311 usually only accepts OPEN or CLOSED status in + its updates. Enable <strong>extended Open311 stauses</strong> if you want to allow extra states to be passed. + Check that your cobrand supports this feature before switching it on." + ) %] + </p> + </div> + <p> + <input type="checkbox" id="send_extended_statuses" name="send_extended_statuses"[% ' checked' IF object.send_extended_statuses %]> + <label for="send_extended_statuses" class="inline">Send extended Open311 statuses with service request updates</label> + </p> + [% END %] +</div> diff --git a/templates/web/base/admin/response_templates_select.html b/templates/web/base/admin/response_templates_select.html index fbe09268e..417be9add 100644 --- a/templates/web/base/admin/response_templates_select.html +++ b/templates/web/base/admin/response_templates_select.html @@ -1,6 +1,6 @@ [% IF problem.response_templates %] <div class="response_templates_select"> - <select id="templates_for_[% for %]" class="js-template-name" data-for="[% for %]" name="response_template"> + <select id="templates_for_[% for %]" class="form-control js-template-name" data-for="[% for %]" name="response_template"> <option value="">[% loc('--Choose a template--') %]</option> [% FOR t IN problem.response_templates %] <option value="[% t.text | html %]"> [% t.title | html %] </option> diff --git a/templates/web/base/admin/responsepriorities/edit.html b/templates/web/base/admin/responsepriorities/edit.html index 89f41a069..4d838eed2 100644 --- a/templates/web/base/admin/responsepriorities/edit.html +++ b/templates/web/base/admin/responsepriorities/edit.html @@ -14,18 +14,17 @@ <input type="text" name="name" class="required form-control" size="30" value="[% rp.name | html %]"> </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> + <strong>[% loc('Description:') %] </strong> + <input type="text" name="description" class="form-control" size="30" value="[% rp.description | html %]"> </p> + + <div class="admin-hint"> + <p> + [% loc('If you only want this priority to be an option for specific categories, pick them here. By default they will show for all categories.') %] + </p> + </div> + [% INCLUDE 'admin/category-checkboxes.html' %] + <p> <label> <input type="checkbox" name="deleted" id="deleted" value="1"[% ' checked' IF rp.deleted %]> diff --git a/templates/web/base/admin/responsepriorities/list.html b/templates/web/base/admin/responsepriorities/list.html index c893a4c70..4c05ca14d 100644 --- a/templates/web/base/admin/responsepriorities/list.html +++ b/templates/web/base/admin/responsepriorities/list.html @@ -4,13 +4,25 @@ <thead> <tr> <th> [% loc('Name') %] </th> + <th> [% loc('Description') %] </th> + <th> [% loc('Categories') %] </th> <th> </th> </tr> </thead> <tbody> [% FOR p IN response_priorities %] <tr [% 'class="is-deleted"' IF p.deleted %]> - <td> [% p.name %] </td> + <td> [% p.name | html %] </td> + <td> [% p.description | html %] </td> + <td> + [% UNLESS p.contacts.size %] + <em>[% loc('All categories') %]</em> + [% ELSE %] + [% FOR contact IN p.contacts %] + [% contact.category %][% ',' UNLESS loop.last %] + [% END %] + [% END %] + </td> <td> <a href="[% c.uri_for('', body.id, p.id) %]" class="btn">[% loc('Edit') %]</a> </td> </tr> [% END %] diff --git a/templates/web/base/admin/template_edit.html b/templates/web/base/admin/template_edit.html index 8ce3c28dd..b2e734756 100644 --- a/templates/web/base/admin/template_edit.html +++ b/templates/web/base/admin/template_edit.html @@ -23,19 +23,14 @@ <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> + + <div class="admin-hint"> + <p> + [% loc('If you only want this template to be an option for specific categories, pick them here. By default they will show for all categories.') %] + </p> + </div> + [% INCLUDE 'admin/category-checkboxes.html' %] + <p> <input type="hidden" name="token" value="[% csrf_token %]" > <input type="submit" class="btn" name="Edit templates" value="[% rt.id ? loc('Save changes') : loc('Create template') %]" > diff --git a/templates/web/base/report/new/extra_name.html b/templates/web/base/report/new/extra_name.html index 2838645af..bad03e37f 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 js-form-name" id="form_fms_extra_title" +<select class="form-control 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/update/form_name.html b/templates/web/base/report/update/form_name.html index 33887117a..926e16878 100644 --- a/templates/web/base/report/update/form_name.html +++ b/templates/web/base/report/update/form_name.html @@ -7,7 +7,7 @@ [% IF can_contribute_as_another_user OR can_contribute_as_body %] <label for="form_as">[% loc('Provide update as') %]</label> - <select id="form_as" class="js-contribute-as" name="form_as"> + <select id="form_as" class="form-control js-contribute-as" name="form_as"> <option value="myself" selected>[% loc('Yourself') %]</option> [% IF can_contribute_as_another_user %] <option value="another_user">[% loc('Another user') %]</option> diff --git a/templates/web/bromley/report/display.html b/templates/web/bromley/report/display.html index 4d3b68f96..9f2089d28 100644 --- a/templates/web/bromley/report/display.html +++ b/templates/web/bromley/report/display.html @@ -73,7 +73,7 @@ [% IF c.user && c.user.belongs_to_body( problem.bodies_str ) %] <label for="form_state">[% loc( 'State' ) %]</label> - <select name="state" id="form_state"> + <select name="state" id="form_state" class="form-control"> [% FOREACH state IN [ ['confirmed', loc('Open')], ['investigating', loc('Investigating')], ['action scheduled', loc('Action Scheduled')], ['in progress', loc('In Progress')], ['duplicate', loc('Duplicate')], diff --git a/templates/web/fixmystreet.com/report/new/extra_name.html b/templates/web/fixmystreet.com/report/new/extra_name.html index 91f70dd8d..dbd971d74 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 js-form-name" id="form_fms_extra_title" +<select class="form-control 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/seesomething/report/new/category.html b/templates/web/seesomething/report/new/category.html index 4b0589e17..f18d4fd02 100644 --- a/templates/web/seesomething/report/new/category.html +++ b/templates/web/seesomething/report/new/category.html @@ -5,7 +5,7 @@ <label for='form_category' class="select"> [%~ loc('Category') ~%] </label>[% =%] - <select name='category' data-theme="c" id='form_category'> + <select name='category' data-theme="c" id='form_category' class="form-control"> [%~ FOREACH cat_op IN category_options ~%] [% cat_op_lc = cat_op | lower =%] <option value='[% cat_op | html %]'[% ' selected' IF report.category == cat_op || category == cat_op_lc ~%] diff --git a/templates/web/zurich/admin/body.html b/templates/web/zurich/admin/body.html index 435f42885..cf860990d 100644 --- a/templates/web/zurich/admin/body.html +++ b/templates/web/zurich/admin/body.html @@ -61,11 +61,6 @@ <input type="hidden" name="token" value="[% csrf_token %]" > <input type="submit" class="btn" name="Create category" value="[% errors ? loc('Save changes') : loc('Create category') %]"> </p> - - <div> - <input type="hidden" name=".cgifields" value="confirmed" > - <input type="hidden" name=".cgifields" value="deleted" > - </div> </form> [% END %] diff --git a/templates/web/zurich/admin/contact-form.html b/templates/web/zurich/admin/contact-form.html new file mode 100644 index 000000000..dddfc6d01 --- /dev/null +++ b/templates/web/zurich/admin/contact-form.html @@ -0,0 +1,21 @@ +<form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8" id="category_edit"> + <p><strong>[% loc('Category:') %] </strong>[% contact.category | html %] + <input type="hidden" name="category" value="[% contact.category | html %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > + + <p><strong>[% loc('Email:') %] </strong> + <input type="text" class="form-control" name="email" value="[% contact.email | html %]" size="30"> + + <p> + <input type="hidden" name="confirmed" value="1"> + <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> + <label class="inline" for="deleted">[% loc('Deleted') %]</label> + <input type="checkbox" name="photo_required" value="1" id="photo_required"[% ' checked' IF contact.get_extra_metadata('photo_required') %]> + <label class="inline" for="photo_required">[% loc('Photo required') %]</label> + </p> + + <p><strong>[% loc('Note:') %] </strong><textarea class="form-control" name="note" rows="3" cols="40"></textarea> + + <input type="hidden" name="posted" value="new"> + <p><input type="submit" class="btn" name="Save changes" value="[% loc('Save changes') %]"> +</form> diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html index ec65cf99f..f87dcb5cf 100644 --- a/templates/web/zurich/admin/report_edit.html +++ b/templates/web/zurich/admin/report_edit.html @@ -107,7 +107,7 @@ <dd>[% problem.get_time_spent %]</dd> [% IF problem.photo %] - <dd data-confirm="[% loc('Rotating this photo will discard unsaved changes to the report.') | html %]"> + <dd data-confirm-msg="[% loc('Rotating this photo will discard unsaved changes to the report.') | html %]"> [% FOR photo IN problem.photos %] <div class="update-img"> <a href="[% c.cobrand.base_url %][% photo.url_temp_full %]" rel="fancy"> diff --git a/web/cobrands/zurich/js.js b/web/cobrands/zurich/js.js index d895789f1..f3977161c 100644 --- a/web/cobrands/zurich/js.js +++ b/web/cobrands/zurich/js.js @@ -122,7 +122,7 @@ $(function() { // If the user has clicked to rotate a photo and has edited other // fields, ask for confirmation before submitting the form if (/rotate_photo/.test(clicked) && form_fields_changed) { - var message = $(this).parent().data('confirm'); + var message = $(this).find("input[name="+clicked+"]").parent().data('confirmMsg'); if (!confirm(message)) { return false; } diff --git a/web/js/fixmystreet-admin.js b/web/js/fixmystreet-admin.js index 6f4580feb..0323b1742 100644 --- a/web/js/fixmystreet-admin.js +++ b/web/js/fixmystreet-admin.js @@ -2,12 +2,13 @@ $(function(){ // available for admin pages // hide the open311_only section and reveal it only when send_method is relevant - var $open311_only = $('.admin-open311-only'); + function hide_or_show_open311(e, hide_fast) { + var $form = $(this).closest("form"); + var $open311_only = $form.find('.admin-open311-only'); - function hide_or_show_open311(hide_fast) { - var send_method = $('#send_method').val(); + var send_method = $(this).val(); var show_open311 = false; - if ($('#endpoint').val()) { + if ($form.find('[name=endpoint]').val()) { show_open311 = true; // always show the form if there is an endpoint value } else if (send_method && !send_method.match(/^(email|noop|refused)$/i)) { show_open311 = true; @@ -23,11 +24,20 @@ $(function(){ } } - if ($open311_only) { - $('#send_method').on('change', hide_or_show_open311); - hide_or_show_open311(true); + if ($('.admin-open311-only').length) { + // Add handler to send_method dropdowns and set initial visibility + $('[name=send_method]').on('change', hide_or_show_open311).each(function() { + hide_or_show_open311.call(this, null, true); + }); } + // Some lists of checkboxes have 'select all/none' links at the top + $("a[data-select-none], a[data-select-all]").click(function(e) { + e.preventDefault(); + var checked = $(this).filter('[data-select-all]').length > 0; + $(this).closest("ul").find('input[type=checkbox]').prop('checked', checked); + }); + // admin hints: maybe better implemented as tooltips? $(".admin-hint").on('click', function(){ @@ -83,10 +93,17 @@ $(function(){ // On category edit page, hide the reputation input if inspection isn't required $("form#category_edit #inspection_required").change(function() { var $p = $("form#category_edit #reputation_threshold").closest("p"); + var $hint = $p.prevUntil().first(); if (this.checked) { $p.removeClass("hidden"); + if ($hint.length) { + $hint.removeClass("hidden"); + } } else { $p.addClass("hidden"); + if ($hint.length) { + $hint.addClass("hidden"); + } } }); }); |