aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/update-schema1
-rw-r--r--perllib/FixMyStreet/App/Controller/Around.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth.pm5
-rw-r--r--perllib/FixMyStreet/App/Controller/My.pm75
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm8
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm10
-rw-r--r--perllib/FixMyStreet/App/Controller/Root.pm1
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm2
-rw-r--r--t/app/controller/my_planned.t4
-rw-r--r--templates/web/base/my/planned.html4
-rw-r--r--templates/web/base/report/_item.html45
-rw-r--r--templates/web/base/report/_main.html10
-rw-r--r--templates/web/base/reports/_list-filters.html3
-rwxr-xr-xtemplates/web/fixmystreet.com/reports/_extras.html1
-rw-r--r--web/cobrands/bristol/base.scss1
-rw-r--r--web/cobrands/bristol/layout.scss1
-rw-r--r--web/cobrands/bromley/base.scss1
-rw-r--r--web/cobrands/bromley/layout.scss1
-rw-r--r--web/cobrands/fixmystreet.com/_colours.scss2
-rw-r--r--web/cobrands/fixmystreet/fixmystreet.js111
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-active-hover.pngbin0 -> 359 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-active-hover.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-active-hover@2x.pngbin0 -> 717 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-active.pngbin0 -> 349 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-active.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-active@2x.pngbin0 -> 669 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-down-hover.pngbin0 -> 122 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-down-hover.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-down-hover@2x.pngbin0 -> 159 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-down.pngbin0 -> 109 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-down.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-down@2x.pngbin0 -> 138 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.pngbin0 -> 514 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover@2x.pngbin0 -> 1045 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-inactive.pngbin0 -> 326 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-inactive.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-inactive@2x.pngbin0 -> 649 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-mini.pngbin0 -> 259 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-mini.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-mini@2x.pngbin0 -> 557 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.pngbin0 -> 487 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-taken-hover@2x.pngbin0 -> 868 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-taken.pngbin0 -> 324 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-taken.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-taken@2x.pngbin0 -> 577 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-up-hover.pngbin0 -> 120 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-up-hover.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-up-hover@2x.pngbin0 -> 161 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-up.pngbin0 -> 109 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-up.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlist-up@2x.pngbin0 -> 139 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlisted-mini.pngbin0 -> 262 bytes
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlisted-mini.svg1
-rw-r--r--web/cobrands/fixmystreet/images/icon-shortlisted-mini@2x.pngbin0 -> 478 bytes
-rw-r--r--web/cobrands/greenwich/base.scss1
-rw-r--r--web/cobrands/greenwich/layout.scss1
-rw-r--r--web/cobrands/oxfordshire/_colours.scss3
-rw-r--r--web/cobrands/oxfordshire/base.scss1
-rw-r--r--web/cobrands/oxfordshire/layout.scss13
-rw-r--r--web/cobrands/sass/_base.scss209
-rw-r--r--web/cobrands/sass/_layout.scss1
-rw-r--r--web/cobrands/sass/_mixins.scss12
-rw-r--r--web/cobrands/sass/_report_list_pins.scss57
65 files changed, 495 insertions, 103 deletions
diff --git a/bin/update-schema b/bin/update-schema
index 479a55c8e..b85ff87f4 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 '0048' if column_exists('response_templates', 'state');
return '0047' if column_exists('response_priorities', 'description');
return '0046' if column_exists('users', 'extra');
return '0045' if table_exists('response_priorities');
diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm
index b4f94bb35..96854b17b 100644
--- a/perllib/FixMyStreet/App/Controller/Around.pm
+++ b/perllib/FixMyStreet/App/Controller/Around.pm
@@ -291,6 +291,8 @@ sub ajax : Path('/ajax') {
# assume this is not cacheable - may need to be more fine-grained later
$c->res->header( 'Cache_Control' => 'max-age=0' );
+ $c->stash->{page} = 'around'; # Needed by _item.html
+
# how far back should we go?
my $all_pins = $c->get_param('all_pins') ? 1 : undef;
my $interval = $all_pins ? undef : $c->cobrand->on_map_default_max_pin_age;
diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm
index c448f8749..6e8057723 100644
--- a/perllib/FixMyStreet/App/Controller/Auth.pm
+++ b/perllib/FixMyStreet/App/Controller/Auth.pm
@@ -516,11 +516,12 @@ sub check_csrf_token : Private {
$token =~ s/ /+/g;
my ($time) = $token =~ /^(\d+)-[0-9a-zA-Z+\/]+$/;
$c->stash->{csrf_time} = $time;
+ my $gen_token = $c->forward('get_csrf_token');
+ delete $c->stash->{csrf_time};
$c->detach('no_csrf_token')
unless $time
&& $time > time() - 3600
- && $token eq $c->forward('get_csrf_token');
- delete $c->stash->{csrf_time};
+ && $token eq $gen_token;
}
sub no_csrf_token : Private {
diff --git a/perllib/FixMyStreet/App/Controller/My.pm b/perllib/FixMyStreet/App/Controller/My.pm
index 51f1687ee..c26cdd5c8 100644
--- a/perllib/FixMyStreet/App/Controller/My.pm
+++ b/perllib/FixMyStreet/App/Controller/My.pm
@@ -3,6 +3,7 @@ use Moose;
use namespace::autoclean;
use JSON::MaybeXS;
+use List::MoreUtils qw(first_index);
BEGIN { extends 'Catalyst::Controller'; }
@@ -30,8 +31,11 @@ sub begin : Private {
sub my : Path : Args(0) {
my ( $self, $c ) = @_;
+ $c->forward('/auth/get_csrf_token');
+
$c->stash->{problems_rs} = $c->cobrand->problems->search(
{ user_id => $c->user->id });
+ $c->forward('/reports/stash_report_sort', [ 'created-desc' ]);
$c->forward('get_problems');
if ($c->get_param('ajax')) {
$c->detach('/reports/ajax', [ 'my/_problem-list.html' ]);
@@ -43,21 +47,54 @@ sub my : Path : Args(0) {
sub planned : Local : Args(0) {
my ( $self, $c ) = @_;
+ $c->forward('/auth/get_csrf_token');
+
$c->detach('/page_error_403_access_denied', [])
unless $c->user->has_body_permission_to('planned_reports');
$c->stash->{problems_rs} = $c->user->active_planned_reports;
+ $c->forward('planned_reorder');
+ $c->forward('/reports/stash_report_sort', [ 'shortlist' ]);
$c->forward('get_problems');
$c->forward('setup_page_data');
}
+sub planned_reorder : Private {
+ my ($self, $c) = @_;
+
+ my @extra = grep { /^shortlist-(up|down|\d+)$/ } keys %{$c->req->params};
+ return unless @extra;
+ my ($reorder) = $extra[0] =~ /^shortlist-(up|down|\d+)$/;
+
+ my @shortlist = sort by_shortlisted $c->stash->{problems_rs}->all;
+
+ # Find where moving problem ID is
+ my $id = $c->get_param('id') || return;
+ my $curr_index = first_index { $_->id == $id } @shortlist;
+ return unless $curr_index > -1;
+
+ if ($reorder eq 'up' && $curr_index > 0) {
+ @shortlist[$curr_index-1,$curr_index] = @shortlist[$curr_index,$curr_index-1];
+ } elsif ($reorder eq 'down' && $curr_index < @shortlist-1) {
+ @shortlist[$curr_index,$curr_index+1] = @shortlist[$curr_index+1,$curr_index];
+ } elsif ($reorder >= 0 && $reorder <= @shortlist-1) { # Must be an index to move it
+ @shortlist[$curr_index,$reorder] = @shortlist[$reorder,$curr_index];
+ }
+
+ # Store new ordering
+ my $i = 1;
+ foreach (@shortlist) {
+ $_->set_extra_metadata('order', $i++);
+ $_->update;
+ }
+}
+
sub get_problems : Private {
my ($self, $c) = @_;
my $p_page = $c->get_param('p') || 1;
$c->forward( '/reports/stash_report_filter_status' );
- $c->forward('/reports/stash_report_sort', [ 'created-desc' ]);
my $pins = [];
my $problems = [];
@@ -73,9 +110,12 @@ sub get_problems : Private {
$c->stash->{filter_category} = $categories;
}
+ my $rows = 50;
+ $rows = 5000 if $c->stash->{sort_key} eq 'shortlist'; # Want all reports
+
my $rs = $c->stash->{problems_rs}->search( $params, {
order_by => $c->stash->{sort_order},
- rows => 50
+ rows => $rows,
} )->include_comment_counts->page( $p_page );
while ( my $problem = $rs->next ) {
@@ -83,6 +123,9 @@ sub get_problems : Private {
push @$pins, $problem->pin_data($c, 'my', private => 1);
push @$problems, $problem;
}
+
+ @$problems = sort by_shortlisted @$problems if $c->stash->{sort_key} eq 'shortlist';
+
$c->stash->{problems_pager} = $rs->pager;
$c->stash->{problems} = $problems;
$c->stash->{pins} = $pins;
@@ -134,27 +177,45 @@ sub planned_change : Path('planned/change') {
my ($self, $c) = @_;
$c->forward('/auth/check_csrf_token');
+ $c->go('planned') if grep { /^shortlist-(up|down|\d+)$/ } keys %{$c->req->params};
+
my $id = $c->get_param('id');
$c->forward( '/report/load_problem_or_display_error', [ $id ] );
- my $change = $c->get_param('change');
+ my $add = $c->get_param('shortlist-add');
+ my $remove = $c->get_param('shortlist-remove');
$c->detach('/page_error_403_access_denied', [])
- unless $change && $change =~ /add|remove/;
+ unless $add || $remove;
- if ($change eq 'add') {
+ if ($add) {
$c->user->add_to_planned_reports($c->stash->{problem});
- } elsif ($change eq 'remove') {
+ } elsif ($remove) {
$c->user->remove_from_planned_reports($c->stash->{problem});
}
if ($c->get_param('ajax')) {
$c->res->content_type('application/json; charset=utf-8');
- $c->res->body(encode_json({ outcome => $change }));
+ $c->res->body(encode_json({ outcome => $add ? 'add' : 'remove' }));
} else {
$c->res->redirect( $c->uri_for_action('report/display', $id) );
}
}
+sub by_shortlisted {
+ my $a_order = $a->get_extra_metadata('order') || 0;
+ my $b_order = $b->get_extra_metadata('order') || 0;
+ if ($a_order && $b_order) {
+ $a_order <=> $b_order;
+ } elsif ($a_order) {
+ -1; # Want non-ordered to come last
+ } elsif ($b_order) {
+ 1; # Want non-ordered to come last
+ } else {
+ # Default to order added to planned reports
+ $a->user_planned_reports->first->id <=> $b->user_planned_reports->first->id;
+ }
+}
+
__PACKAGE__->meta->make_immutable;
1;
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index e2569d2e9..6d90b6ee9 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -83,6 +83,14 @@ sub report_new : Path : Args(0) {
$c->forward('initialize_report');
$c->forward('/auth/get_csrf_token');
+ my @shortlist = grep { /^shortlist-(add|remove)-(\d+)$/ } keys %{$c->req->params};
+ if (@shortlist) {
+ my ($cmd, $id) = $shortlist[0] =~ /^shortlist-(add|remove)-(\d+)$/;
+ $c->req->params->{id} = $id;
+ $c->req->params->{"shortlist-$cmd"} = 1;
+ $c->detach('/my/planned_change');
+ }
+
# work out the location for this report and do some checks
# Also show map if we're just updating the filters
return $c->forward('redirect_to_around')
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index f2c43b5ee..2635b7b7a 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -108,6 +108,8 @@ Show the summary page for a particular ward.
sub ward : Path : Args(2) {
my ( $self, $c, $body, $ward ) = @_;
+ $c->forward('/auth/get_csrf_token');
+
$c->forward( 'body_check', [ $body ] );
$c->forward( 'ward_check', [ $ward ] )
if $ward;
@@ -513,13 +515,17 @@ sub stash_report_sort : Private {
);
my $sort = $c->get_param('sort') || $default;
- $sort = $default unless $sort =~ /^((updated|created)-(desc|asc)|comments-desc)$/;
+ $sort = $default unless $sort =~ /^((updated|created)-(desc|asc)|comments-desc|shortlist)$/;
+ $c->stash->{sort_key} = $sort;
+
+ # Going to do this sorting code-side
+ $sort = 'created-desc' if $sort eq 'shortlist';
+
$sort =~ /^(updated|created|comments)-(desc|asc)$/;
my $order_by = $types{$1} || $1;
my $dir = $2;
$order_by = { -desc => $order_by } if $dir eq 'desc';
- $c->stash->{sort_key} = $sort;
$c->stash->{sort_order} = $order_by;
return 1;
}
diff --git a/perllib/FixMyStreet/App/Controller/Root.pm b/perllib/FixMyStreet/App/Controller/Root.pm
index 20a871b17..4f098dfc3 100644
--- a/perllib/FixMyStreet/App/Controller/Root.pm
+++ b/perllib/FixMyStreet/App/Controller/Root.pm
@@ -58,6 +58,7 @@ sub index : Path : Args(0) {
return;
}
+ $c->forward('/auth/get_csrf_token');
}
=head2 default
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index 135f9b4a5..cf6de9a76 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -382,6 +382,8 @@ around add_to_planned_reports => sub {
around remove_from_planned_reports => sub {
my ($orig, $self, $report) = @_;
$self->user_planned_reports->active->for_report($report->id)->remove();
+ $report->unset_extra_metadata('order');
+ $report->update;
};
sub active_planned_reports {
diff --git a/t/app/controller/my_planned.t b/t/app/controller/my_planned.t
index 7bd1dd2cd..d66673589 100644
--- a/t/app/controller/my_planned.t
+++ b/t/app/controller/my_planned.t
@@ -40,9 +40,9 @@ $mech->content_contains('Test Title');
$mech->get_ok($problem->url);
$mech->content_contains('Shortlisted');
-$mech->submit_form_ok({ with_fields => { change => 'remove' } });
+$mech->submit_form_ok({ with_fields => { 'shortlist-remove' => 1 } });
$mech->content_contains('Shortlist');
-$mech->submit_form_ok({ with_fields => { change => 'add' } });
+$mech->submit_form_ok({ with_fields => { 'shortlist-add' => 1 } });
$mech->content_contains('Shortlisted');
done_testing();
diff --git a/templates/web/base/my/planned.html b/templates/web/base/my/planned.html
index eb67247c4..d1a6b7b1b 100644
--- a/templates/web/base/my/planned.html
+++ b/templates/web/base/my/planned.html
@@ -22,11 +22,11 @@
[% END %]
<section class="full-width">
-[% INCLUDE "reports/_list-filters.html", use_form_wrapper = 1 %]
+[% INCLUDE "reports/_list-filters.html", use_form_wrapper = 1 shortlist = 1 %]
<div class="js-pagination">
[% INCLUDE 'pagination.html', pager = problems_pager, param = 'p' %]
</div>
-[% INCLUDE 'my/_problem-list.html' %]
+[% INCLUDE 'my/_problem-list.html' shortlist = 1 %]
</section>
</div>
diff --git a/templates/web/base/report/_item.html b/templates/web/base/report/_item.html
index 02457e5a0..e233ff09f 100644
--- a/templates/web/base/report/_item.html
+++ b/templates/web/base/report/_item.html
@@ -2,6 +2,30 @@
[% PROCESS 'admin/report_blocks.html' ~%]
[% END ~%]
+[% IF c.user.has_permission_to('planned_reports', problem.bodies_str_ids) ~%]
+ [% item_extra_class = "item-list__item--indented" ~%]
+ [% item_action = BLOCK ~%]
+ <input type="submit" value="1"
+ data-label-remove="[% loc('Remove from shortlist') %]"
+ data-label-add="[% loc('Add to shortlist') %]"
+ [% IF c.user.is_planned_report(problem) ~%]
+ name="shortlist-remove" title="[% loc('Remove from shortlist') %]" class="item-list__item__shortlist-remove"
+ [%~ ELSE ~%]
+ name="shortlist-add" title="[% loc('Add to shortlist') %]" class="item-list__item__shortlist-[% IF problem.shortlisted_user %]take[% ELSE %]add[% END %]"
+ [%~ END ~%]
+ >
+ [%~ END %]
+[% END %]
+
+[% IF shortlist %]
+ [% item_extra_class = "item-list__item--indented item-list__item--act-and-sort" %]
+ [% item_action = BLOCK %]
+ [% item_action %]
+ <input type="submit" name="shortlist-up" value="[% loc('Up one') %]" title="[% loc('Up one') %]" class="item-list__item__shortlist-up" [% IF loop.first %]disabled[% END %]>
+ <input type="submit" name="shortlist-down" value="[% loc('Down one') %]" title="[% loc('Down one') %]" class="item-list__item__shortlist-down" [% IF loop.last %]disabled[% END %]>
+ [% END %]
+[% END %]
+
<li class="item-list__item item-list--reports__item [% item_extra_class %]"
data-report-id="[% problem.id | html %]" data-lastupdate="[% problem.lastupdate %]">
<a href="[% c.cobrand.base_url_for_report( problem ) %][% problem.url %]">
@@ -13,6 +37,13 @@
<div class="item-list__description">[% problem.detail | html %]</div>
[% END %]
<small>
+ [% IF NOT no_fixed AND problem.is_fixed %]
+ <span class="item-list__item__state">[% loc('Fixed') %]</span>
+ [% ELSIF NOT no_fixed AND problem.is_closed %]
+ <span class="item-list__item__state">[% loc('Closed') %]</span>
+ [% ELSIF problem.response_priority AND (c.user.has_permission_to('report_edit_priority', problem.bodies_str_ids) OR c.user.has_permission_to('report_inspect', problem.bodies_str_ids)) %]
+ <span class="item-list__item__state">[% problem.response_priority.name %]</span>
+ [% END %]
[%- IF c.cobrand.moniker != 'fixamingata' %] [%# Default: %]
[%- prettify_dt( problem.confirmed, 1 ) %]
[%- ELSE %] [%# Swedish cobrand fixamingata: %]
@@ -29,11 +60,6 @@
[% ELSIF problem.bodies_str_ids.size == 0 %] [% loc('(not sent to council)') %]
[% END %]
[% END %]
- [% IF NOT no_fixed AND problem.is_fixed %]
- [% loc('(fixed)') %]
- [% ELSIF NOT no_fixed AND problem.is_closed %]
- [% loc('(closed)') %]
- [% END %]
</small>
[% IF c.user.has_permission_to('report_inspect', problem.bodies_str_ids) %]
@@ -85,4 +111,13 @@
</a>
+[% IF item_action AND page != 'around' %]
+ <form method="post" action="/my/planned/change">
+ <input type="hidden" name="id" value="[% problem.id %]">
+ <input type="hidden" name="token" value="[% csrf_token %]">
+ [% item_action %]
+ </form>
+[% ELSIF item_action ~%]
+ [% item_action.replace('("shortlist-[^"]*)', '$1-' _ problem.id) %]
+[% END ~%]
</li>
diff --git a/templates/web/base/report/_main.html b/templates/web/base/report/_main.html
index d5224f23e..9431ef2ce 100644
--- a/templates/web/base/report/_main.html
+++ b/templates/web/base/report/_main.html
@@ -11,7 +11,7 @@
<form method="post" action="/my/planned/change" id="planned_form" class="hidden-label-target">
<input type="hidden" name="id" value="[% problem.id %]">
<input type="hidden" name="token" value="[% csrf_token %]">
- <input type="hidden" name="change" value="[% IF c.user.is_planned_report(problem) %]remove[% ELSE %]add[% END %]">
+ <input type="hidden" name="[% IF c.user.is_planned_report(problem) %]shortlist-remove[% ELSE %]shortlist-add[% END %]" value="1">
<p><input
type="submit"
id="shortlist-report"
@@ -19,12 +19,16 @@
data-label-add="[% loc('Add to shortlist') %]"
data-value-remove="[% loc('Shortlisted') %]"
data-value-add="[% loc('Shortlist') %]"
+ data-class-remove="btn--shortlisted"
+ data-class-add="btn--shortlist"
[%~ IF c.user.is_planned_report(problem) ~%]
value="[% loc('Shortlisted') %]"
aria-label="[% loc('Remove from shortlist') %]"
+ class="btn--shortlisted"
[%~ ELSE ~%]
value="[% loc('Shortlist') %]"
aria-label="[% loc('Add to shortlist') %]"
+ class="btn--shortlist"
[%~ END ~%]
></p>
</form>
@@ -127,9 +131,9 @@
[% END %]
[% IF c.user.has_permission_to('planned_reports', problem.bodies_str_ids) %]
[%~ IF c.user.is_planned_report(problem) ~%]
- <label class="btn" for="shortlist-report" role="menuitem" aria-label="[% loc('Remove from shortlist') %]">[% loc('Shortlisted') %]</label>
+ <label class="btn btn--shortlisted" for="shortlist-report" role="menuitem" aria-label="[% loc('Remove from shortlist') %]">[% loc('Shortlisted') %]</label>
[%~ ELSE ~%]
- <label class="btn" for="shortlist-report" role="menuitem" aria-label="[% loc('Add to shortlist') %]">[% loc('Shortlist') %]</label>
+ <label class="btn btn--shortlist" for="shortlist-report" role="menuitem" aria-label="[% loc('Add to shortlist') %]">[% loc('Shortlist') %]</label>
[%~ END ~%]
[% END %]
</div>
diff --git a/templates/web/base/reports/_list-filters.html b/templates/web/base/reports/_list-filters.html
index 9c2a74e57..05fe6123b 100644
--- a/templates/web/base/reports/_list-filters.html
+++ b/templates/web/base/reports/_list-filters.html
@@ -32,6 +32,9 @@
<p class="report-list-filters">
<label for="sort">[% loc('Sort by') %]</label>
<select class="form-control" name="sort" id="sort">
+ [% IF shortlist %]
+ <option value="shortlist"[% ' selected' IF sort_key == 'shortlist' %]>[% loc('Manual order') %]</option>
+ [% END %]
<option value="created-desc"[% ' selected' IF sort_key == 'created-desc' %]>[% loc('Newest') %]</option>
<option value="created-asc"[% ' selected' IF sort_key == 'created-asc' %]>[% loc('Oldest') %]</option>
<option value="updated-desc"[% ' selected' IF sort_key == 'updated-desc' %]>[% loc('Recently updated') %]</option>
diff --git a/templates/web/fixmystreet.com/reports/_extras.html b/templates/web/fixmystreet.com/reports/_extras.html
index 6fa067d1c..824fec3ec 100755
--- a/templates/web/fixmystreet.com/reports/_extras.html
+++ b/templates/web/fixmystreet.com/reports/_extras.html
@@ -4,7 +4,6 @@
'Bromley Council' = 'fix.bromley.gov.uk'
'Bristol City Council' = 'fixmystreet.bristol.gov.uk'
'East Hertfordshire District Council' = 'fixmystreet.eastherts.gov.uk'
- 'Harrogate Borough Council' = 'harrogate.fixmystreet.com'
'Hart District Council' = 'hart.fixmystreet.com'
'Oxfordshire County Council' = 'fixmystreet.oxfordshire.gov.uk'
'Stevenage Borough Council' = 'stevenage.fixmystreet.com',
diff --git a/web/cobrands/bristol/base.scss b/web/cobrands/bristol/base.scss
index 746e17064..c92b46ec3 100644
--- a/web/cobrands/bristol/base.scss
+++ b/web/cobrands/bristol/base.scss
@@ -4,6 +4,7 @@
@import "../sass/mixins";
@import "../sass/base";
+@import "../sass/report_list_pins";
// Put the BCC logo in place, and reveal the 'bristol.gov.uk' text alongside it
#site-logo {
diff --git a/web/cobrands/bristol/layout.scss b/web/cobrands/bristol/layout.scss
index 02894e083..3b9dfa1b6 100644
--- a/web/cobrands/bristol/layout.scss
+++ b/web/cobrands/bristol/layout.scss
@@ -1,7 +1,6 @@
@import "_colours";
@import "_fonts";
@import "../sass/layout";
-@import "../sass/report_list_pins";
#site-header {
background-color: $g1;
diff --git a/web/cobrands/bromley/base.scss b/web/cobrands/bromley/base.scss
index 5661632a3..0d028d190 100644
--- a/web/cobrands/bromley/base.scss
+++ b/web/cobrands/bromley/base.scss
@@ -4,6 +4,7 @@
@import "../sass/mixins";
@import "../sass/base";
+@import "../sass/report_list_pins";
// Override the site logo
#site-logo{
diff --git a/web/cobrands/bromley/layout.scss b/web/cobrands/bromley/layout.scss
index a8c1f35ce..71d7cbc47 100644
--- a/web/cobrands/bromley/layout.scss
+++ b/web/cobrands/bromley/layout.scss
@@ -1,6 +1,5 @@
@import "_colours";
@import "../sass/layout";
-@import "../sass/report_list_pins";
// Alter the logo and the header on every page *but* the map page. On the map
// page it stays small like in base.css
diff --git a/web/cobrands/fixmystreet.com/_colours.scss b/web/cobrands/fixmystreet.com/_colours.scss
index 908356d36..c72e48d45 100644
--- a/web/cobrands/fixmystreet.com/_colours.scss
+++ b/web/cobrands/fixmystreet.com/_colours.scss
@@ -20,6 +20,6 @@ $col_fixed_label: #00BD08;
$col_fixed_label_dark: #4B8304;
$itemlist_item_background: #f6f6f6;
-$itemlist_item_background_hover: mix(#fff, $primary, 50%);
+$itemlist_item_background_hover: mix(#fff, $primary, 70%);
$layout_front_stats_color: #222;
diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js
index 190978d45..bec4bc295 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -213,6 +213,15 @@ fixmystreet.geolocate = {
}
};
+fixmystreet.update_list_item_buttons = function($list) {
+ if (!$list) {
+ return;
+ }
+ $list.find('[name="shortlist-up"], [name="shortlist-down"]').prop('disabled', false);
+ $list.children(':first-child').find('[name="shortlist-up"]').prop('disabled', true);
+ $list.children(':last-child').find('[name="shortlist-down"]').prop('disabled', true);
+};
+
fixmystreet.set_up = fixmystreet.set_up || {};
$.extend(fixmystreet.set_up, {
basics: function() {
@@ -227,7 +236,7 @@ $.extend(fixmystreet.set_up, {
$('#pc').focus();
// In case we've come here by clicking back to a form that disabled a submit button
- $('input[type=submit]').removeAttr('disabled');
+ $('form.validate input[type=submit]').removeAttr('disabled');
$('[data-confirm]').on('click', function() {
return confirm(this.getAttribute('data-confirm'));
@@ -313,31 +322,35 @@ $.extend(fixmystreet.set_up, {
}
e.preventDefault();
var $form = $(this),
- $change = $form.find("input[name='change']" ),
$submit = $form.find("input[type='submit']" ),
$labels = $('label[for="' + $submit.attr('id') + '"]'),
problemId = $form.find("input[name='id']").val(),
data = $form.serialize() + '&ajax=1',
changeValue,
buttonLabel,
- buttonValue;
+ buttonValue,
+ classToAdd,
+ classToRemove;
$.post(this.action, data, function(data) {
if (data.outcome == 'add') {
- changeValue = "remove";
+ $form.find("input[name='shortlist-add']" ).attr('name', 'shortlist-remove');
buttonLabel = $submit.data('label-remove');
buttonValue = $submit.data('value-remove');
+ classToAdd = $submit.data('class-remove');
+ classToRemove = $submit.data('class-add');
$('.shortlisted-status').remove();
$(document).trigger('shortlist-add', problemId);
} else if (data.outcome == 'remove') {
- changeValue = "add";
+ $form.find("input[name='shortlist-remove']" ).attr('name', 'shortlist-add');
buttonLabel = $submit.data('label-add');
buttonValue = $submit.data('value-add');
$(document).trigger('shortlist-remove', problemId);
+ classToAdd = $submit.data('class-add');
+ classToRemove = $submit.data('class-remove');
}
- $change.val(changeValue);
- $submit.val(buttonValue).attr('aria-label', buttonLabel);
- $labels.text(buttonValue).attr('aria-label', buttonLabel);
+ $submit.val(buttonValue).attr('aria-label', buttonLabel).removeClass(classToRemove).addClass(classToAdd);
+ $labels.text(buttonValue).attr('aria-label', buttonLabel).removeClass(classToRemove).addClass(classToAdd);
});
});
},
@@ -474,6 +487,88 @@ $.extend(fixmystreet.set_up, {
$("#js-change-duplicate-report").click(refresh_duplicate_list);
},
+ list_item_actions: function() {
+ function toggle_shortlist(btn, sw, id) {
+ btn.attr('class', 'item-list__item__shortlist-' + sw);
+ btn.attr('title', btn.data('label-' + sw));
+ if (id) {
+ sw += '-' + id;
+ }
+ btn.attr('name', 'shortlist-' + sw);
+ }
+
+ $('.item-list').on('click', ':submit', function(e) {
+ e.preventDefault();
+
+ var $submitButton = $(this);
+ var whatUserWants = $submitButton.prop('name');
+ var data;
+ var $item;
+ var $list;
+ var $hiddenInput;
+ var report_id;
+ if (fixmystreet.page === 'around') {
+ // Deal differently because one big form
+ var parts = whatUserWants.split('-');
+ whatUserWants = parts[0] + '-' + parts[1];
+ report_id = parts[2];
+ var token = $('[name=token]').val();
+ data = whatUserWants + '=1&token=' + token + '&id=' + report_id;
+ } else {
+ var $form = $(this).parents('form');
+ $item = $form.parent('.item-list__item');
+ $list = $item.parent('.item-list');
+
+ // The server expects to be told which button/input triggered the form
+ // submission. But $form.serialize() doesn't know that. So we inject a
+ // hidden input into the form, that can pass the name and value of the
+ // submit button to the server, as it expects.
+ $hiddenInput = $('<input>').attr({
+ type: 'hidden',
+ name: whatUserWants,
+ value: $submitButton.prop('value')
+ }).appendTo($form);
+ data = $form.serialize() + '&ajax=1';
+ }
+
+ // Update UI while the ajax request is sent in the background.
+ if ('shortlist-down' === whatUserWants) {
+ $item.insertAfter( $item.next() );
+ } else if ('shortlist-up' === whatUserWants) {
+ $item.insertBefore( $item.prev() );
+ } else if ('shortlist-remove' === whatUserWants) {
+ toggle_shortlist($submitButton, 'add', report_id);
+ } else if ('shortlist-add' === whatUserWants) {
+ toggle_shortlist($submitButton, 'remove', report_id);
+ }
+
+ // Items have moved around. We need to make sure the "up" button on the
+ // first item, and the "down" button on the last item, are disabled.
+ fixmystreet.update_list_item_buttons($list);
+
+ $.ajax({
+ url: '/my/planned/change',
+ type: 'POST',
+ data: data
+ }).fail(function() {
+ // Undo the UI changes we made.
+ if ('shortlist-down' === whatUserWants) {
+ $item.insertBefore( $item.prev() );
+ } else if ('shortlist-up' === whatUserWants) {
+ $item.insertAfter( $item.next() );
+ } else if ('shortlist-remove' === whatUserWants) {
+ toggle_shortlist($submitButton, 'remove', report_id);
+ } else if ('shortlist-add' === whatUserWants) {
+ toggle_shortlist($submitButton, 'add', report_id);
+ }
+ fixmystreet.update_list_item_buttons($list);
+ }).complete(function() {
+ if ($hiddenInput) {
+ $hiddenInput.remove();
+ }
+ });
+ });
+ },
contribute_as: function() {
$('.content').on('change', '.js-contribute-as', function(){
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-active-hover.png b/web/cobrands/fixmystreet/images/icon-shortlist-active-hover.png
new file mode 100644
index 000000000..a2574d407
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-active-hover.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-active-hover.svg b/web/cobrands/fixmystreet/images/icon-shortlist-active-hover.svg
new file mode 100644
index 000000000..054b98134
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-active-hover.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icon-shortlist-active-hover</title><defs><path d="M5.1 22.832l6.9-3.627 6.9 3.627c.286-.192.565-.395.835-.61l-1.318-7.68L24 9.103c-.093-.334-.2-.66-.32-.983l-7.714-1.122L12.518.01C12.346.005 12.173 0 12 0c-.173 0-.346.004-.518.01L8.034 7 .32 8.118c-.12.323-.227.65-.32.983l5.583 5.443-1.318 7.68c.27.214.55.417.836.61z" id="a"/><mask id="b" x="0" y="0" width="24" height="22.832" fill="#fff"><use xlink:href="#a"/></mask></defs><use mask="url(#b)" xlink:href="#a" stroke="#000" stroke-width="4" fill="#000" fill-rule="evenodd" stroke-opacity=".2" fill-opacity=".15"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-active-hover@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-active-hover@2x.png
new file mode 100644
index 000000000..b52123a4a
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-active-hover@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-active.png b/web/cobrands/fixmystreet/images/icon-shortlist-active.png
new file mode 100644
index 000000000..e35ecb179
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-active.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-active.svg b/web/cobrands/fixmystreet/images/icon-shortlist-active.svg
new file mode 100644
index 000000000..fcf677a0f
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-active.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlist-active</title><path d="M5.1 22.832l6.9-3.627 6.9 3.627c.286-.192.565-.395.835-.61l-1.318-7.68L24 9.103c-.093-.334-.2-.66-.32-.983l-7.714-1.122L12.518.01C12.346.005 12.173 0 12 0c-.173 0-.346.004-.518.01L8.034 7 .32 8.118c-.12.323-.227.65-.32.983l5.583 5.443-1.318 7.68c.27.214.55.417.836.61z" fill="#00BD08" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-active@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-active@2x.png
new file mode 100644
index 000000000..bcd5d8c0d
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-active@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-down-hover.png b/web/cobrands/fixmystreet/images/icon-shortlist-down-hover.png
new file mode 100644
index 000000000..c2151f55e
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-down-hover.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-down-hover.svg b/web/cobrands/fixmystreet/images/icon-shortlist-down-hover.svg
new file mode 100644
index 000000000..c8ab5b2b3
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-down-hover.svg
@@ -0,0 +1 @@
+<svg width="24" height="14" viewBox="0 0 24 14" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlist-down-hover</title><path d="M10 6h4V0h-4v6zm2 8l8-8H4l8 8z" fill="#00BD08" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-down-hover@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-down-hover@2x.png
new file mode 100644
index 000000000..3deb4c1d1
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-down-hover@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-down.png b/web/cobrands/fixmystreet/images/icon-shortlist-down.png
new file mode 100644
index 000000000..df700f7cd
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-down.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-down.svg b/web/cobrands/fixmystreet/images/icon-shortlist-down.svg
new file mode 100644
index 000000000..495f7d647
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-down.svg
@@ -0,0 +1 @@
+<svg width="24" height="14" viewBox="0 0 24 14" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlist-down</title><path d="M10 6h4V0h-4v6zm2 8l8-8H4l8 8z" fill="#000" fill-rule="evenodd" fill-opacity=".3"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-down@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-down@2x.png
new file mode 100644
index 000000000..cfdadf2e4
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-down@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.png b/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.png
new file mode 100644
index 000000000..897634bee
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.svg b/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.svg
new file mode 100644
index 000000000..05239ef51
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icon-shortlist-inactive-hover</title><defs><path d="M5.1 22.832l6.9-3.627 6.9 3.627c.286-.192.565-.395.835-.61l-1.318-7.68L24 9.103c-.093-.334-.2-.66-.32-.983l-7.714-1.122L12.518.01C12.346.005 12.173 0 12 0c-.173 0-.346.004-.518.01L8.034 7 .32 8.118c-.12.323-.227.65-.32.983l5.583 5.443-1.318 7.68c.27.214.55.417.836.61z" id="a"/><mask id="b" x="0" y="0" width="24" height="22.832" fill="#fff"><use xlink:href="#a"/></mask></defs><use mask="url(#b)" xlink:href="#a" stroke-width="4" stroke="#00BD08" fill="#00BD08" fill-rule="evenodd" fill-opacity=".25"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover@2x.png
new file mode 100644
index 000000000..b561473fd
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-inactive-hover@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-inactive.png b/web/cobrands/fixmystreet/images/icon-shortlist-inactive.png
new file mode 100644
index 000000000..66d9684fb
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-inactive.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-inactive.svg b/web/cobrands/fixmystreet/images/icon-shortlist-inactive.svg
new file mode 100644
index 000000000..b2709859e
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-inactive.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icon-shortlist-inactive</title><defs><path d="M5.1 22.832l6.9-3.627 6.9 3.627c.286-.192.565-.395.835-.61l-1.318-7.68L24 9.103c-.093-.334-.2-.66-.32-.983l-7.714-1.122L12.518.01C12.346.005 12.173 0 12 0c-.173 0-.346.004-.518.01L8.034 7 .32 8.118c-.12.323-.227.65-.32.983l5.583 5.443-1.318 7.68c.27.214.55.417.836.61z" id="a"/><mask id="b" x="0" y="0" width="24" height="22.832" fill="#fff"><use xlink:href="#a"/></mask></defs><use mask="url(#b)" xlink:href="#a" stroke="#000" stroke-width="4" fill="none" fill-rule="evenodd" stroke-opacity=".3"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-inactive@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-inactive@2x.png
new file mode 100644
index 000000000..47b86d144
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-inactive@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-mini.png b/web/cobrands/fixmystreet/images/icon-shortlist-mini.png
new file mode 100644
index 000000000..730dd49df
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-mini.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-mini.svg b/web/cobrands/fixmystreet/images/icon-shortlist-mini.svg
new file mode 100644
index 000000000..98b89ab2e
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-mini.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icon-shortlist</title><defs><path d="M3.4 15.22L8 12.804l4.6 2.418c.19-.126.377-.262.557-.405l-.88-5.12L16 6.067c-.062-.222-.133-.44-.212-.654l-5.144-.747-2.3-4.66C8.232.003 8.117 0 8 0c-.116 0-.23.002-.345.007l-2.3 4.66-5.143.746c-.08.214-.15.432-.212.654l3.722 3.628-.88 5.12c.18.143.367.28.56.406z" id="a"/><mask id="b" x="0" y="0" width="16" height="15.221" fill="#fff"><use xlink:href="#a"/></mask></defs><use mask="url(#b)" xlink:href="#a" stroke-width="2" stroke="#000" fill="none" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-mini@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-mini@2x.png
new file mode 100644
index 000000000..5a332f431
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-mini@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.png b/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.png
new file mode 100644
index 000000000..0069de106
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.svg b/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.svg
new file mode 100644
index 000000000..b9442e004
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlist-taken-hover</title><g fill="none" fill-rule="evenodd"><path d="M4.095 19.326l5.537-2.91 5.537 2.91c.23-.153.454-.316.67-.488l-1.057-6.165 4.48-4.368c-.074-.267-.16-.53-.255-.788l-6.192-.9-2.77-5.61C9.91 1.004 9.772 1 9.633 1c-.14 0-.278.003-.415.008l-2.77 5.61-6.19.9c-.097.257-.182.52-.257.787l4.48 4.368-1.056 6.165c.216.172.44.335.67.488z" fill="#00BD08"/><path d="M17.777 17.18c.142-.055.277-.118.402-.187.048-.026.102-.04.157-.04h.176c.057 0 .112.014.16.042 1.935.496 3.733 1.535 5.206 3.007.064.064.1.154.1.247L24 21.64c0 .19-.15.346-.336.346H8.336c-.185 0-.336-.156-.336-.346l-.02-1.393c0-.094.038-.183.103-.248.246-.246.5-.48.765-.7l.784-.414 4.335 2.28L17 21l.98-2.63-.203-1.19zm-.294-1.713c1.465-.742 2.498-2.538 2.498-4.635v-.167l-2.845 2.772.348 2.03z" fill-opacity=".3" fill="#000"/></g></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover@2x.png
new file mode 100644
index 000000000..3e8bbcd58
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-taken-hover@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-taken.png b/web/cobrands/fixmystreet/images/icon-shortlist-taken.png
new file mode 100644
index 000000000..f332d52f1
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-taken.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-taken.svg b/web/cobrands/fixmystreet/images/icon-shortlist-taken.svg
new file mode 100644
index 000000000..85154a8fb
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-taken.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlist-taken</title><path d="M12.167 5.303l-2.12-4.295C9.91 1.003 9.77 1 9.632 1c-.14 0-.278.003-.415.008l-2.77 5.61-6.19.9c-.097.257-.182.52-.257.787l4.48 4.368-1.056 6.165c.216.172.44.335.67.488L7.91 17.32c1.074-.93 2.244-1.644 3.47-2.116-.867-1.217-1.39-2.783-1.39-4.49 0-2.178.848-4.124 2.177-5.41zm6.495 11.686c.004 0 .008.003.012.005 1.934.496 3.732 1.535 5.205 3.007.064.064.1.154.1.247L24 21.64c0 .19-.15.346-.336.346H8.336c-.185 0-.336-.156-.336-.346l-.02-1.393c0-.094.038-.183.103-.248 1.477-1.476 3.28-2.516 5.22-3.012.806.473 1.716.74 2.678.74.965 0 1.876-.268 2.682-.74zm-2.68-1.158c2.208 0 4-2.24 4-5 0-2.762-1.792-5-4-5-2.21 0-4 2.238-4 5 0 2.76 1.79 5 4 5z" fill="#000" fill-rule="evenodd" fill-opacity=".3"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-taken@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-taken@2x.png
new file mode 100644
index 000000000..1c5759701
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-taken@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-up-hover.png b/web/cobrands/fixmystreet/images/icon-shortlist-up-hover.png
new file mode 100644
index 000000000..d518fa029
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-up-hover.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-up-hover.svg b/web/cobrands/fixmystreet/images/icon-shortlist-up-hover.svg
new file mode 100644
index 000000000..fe3a941e1
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-up-hover.svg
@@ -0,0 +1 @@
+<svg width="24" height="14" viewBox="0 0 24 14" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlist-up-hover</title><path d="M10 8h4v6h-4V8zm2-8l8 8H4l8-8z" fill="#00BD08" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-up-hover@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-up-hover@2x.png
new file mode 100644
index 000000000..233864de9
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-up-hover@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-up.png b/web/cobrands/fixmystreet/images/icon-shortlist-up.png
new file mode 100644
index 000000000..09ce57064
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-up.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-up.svg b/web/cobrands/fixmystreet/images/icon-shortlist-up.svg
new file mode 100644
index 000000000..c99767267
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-up.svg
@@ -0,0 +1 @@
+<svg width="24" height="14" viewBox="0 0 24 14" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlist-up</title><path d="M10 8h4v6h-4V8zm2-8l8 8H4l8-8z" fill="#000" fill-rule="evenodd" fill-opacity=".3"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlist-up@2x.png b/web/cobrands/fixmystreet/images/icon-shortlist-up@2x.png
new file mode 100644
index 000000000..922cc0a94
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlist-up@2x.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlisted-mini.png b/web/cobrands/fixmystreet/images/icon-shortlisted-mini.png
new file mode 100644
index 000000000..94cdd14fb
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlisted-mini.png
Binary files differ
diff --git a/web/cobrands/fixmystreet/images/icon-shortlisted-mini.svg b/web/cobrands/fixmystreet/images/icon-shortlisted-mini.svg
new file mode 100644
index 000000000..1df25d7e7
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlisted-mini.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><title>icon-shortlisted</title><path d="M3.4 15.22L8 12.804l4.6 2.418c.19-.126.377-.262.557-.405l-.88-5.12L16 6.067c-.062-.222-.133-.44-.212-.654l-5.144-.747-2.3-4.66C8.232.003 8.117 0 8 0c-.116 0-.23.002-.345.007l-2.3 4.66-5.143.746c-.08.214-.15.432-.212.654l3.722 3.628-.88 5.12c.18.143.367.28.56.406z" fill="#00BD08" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/web/cobrands/fixmystreet/images/icon-shortlisted-mini@2x.png b/web/cobrands/fixmystreet/images/icon-shortlisted-mini@2x.png
new file mode 100644
index 000000000..8da64e9ec
--- /dev/null
+++ b/web/cobrands/fixmystreet/images/icon-shortlisted-mini@2x.png
Binary files differ
diff --git a/web/cobrands/greenwich/base.scss b/web/cobrands/greenwich/base.scss
index 756b2d60a..0c52bd5da 100644
--- a/web/cobrands/greenwich/base.scss
+++ b/web/cobrands/greenwich/base.scss
@@ -4,6 +4,7 @@
@import "../sass/mixins";
@import "../sass/base";
+@import "../sass/report_list_pins";
body.frontpage #site-logo,
#site-logo
diff --git a/web/cobrands/greenwich/layout.scss b/web/cobrands/greenwich/layout.scss
index 54150cfd4..db06c9424 100644
--- a/web/cobrands/greenwich/layout.scss
+++ b/web/cobrands/greenwich/layout.scss
@@ -1,7 +1,6 @@
@import "_colours";
@import "_fonts";
@import "../sass/layout";
-@import "../sass/report_list_pins";
$fixed_page_width: 990px;
diff --git a/web/cobrands/oxfordshire/_colours.scss b/web/cobrands/oxfordshire/_colours.scss
index a8a78dc6e..ba0597bb8 100644
--- a/web/cobrands/oxfordshire/_colours.scss
+++ b/web/cobrands/oxfordshire/_colours.scss
@@ -25,6 +25,9 @@ $col_click_map: $oxfordshire_lt_green;
$col_fixed_label: $oxfordshire_lt_green;
$col_fixed_label_dark: mix(#000, $oxfordshire_lt_green, 50%);
+$itemlist_item_background: $oxfordshire_very_light_green;
+$itemlist_item_background_hover: #e3f1d5; // darker version of $oxfordshire_very_light_green
+
// Oxfordshire have toasty orange buttons
$oxfordshire_button_base: #F35A0E;
diff --git a/web/cobrands/oxfordshire/base.scss b/web/cobrands/oxfordshire/base.scss
index 0cc621310..49a1ac66c 100644
--- a/web/cobrands/oxfordshire/base.scss
+++ b/web/cobrands/oxfordshire/base.scss
@@ -4,6 +4,7 @@
@import "../sass/base";
@import "../sass/top-banner";
+@import "../sass/report_list_pins";
#site-header {
background: none;
diff --git a/web/cobrands/oxfordshire/layout.scss b/web/cobrands/oxfordshire/layout.scss
index 22edca768..726b298ff 100644
--- a/web/cobrands/oxfordshire/layout.scss
+++ b/web/cobrands/oxfordshire/layout.scss
@@ -4,7 +4,6 @@ $mappage-header-height: 64px;
@import "_colours";
@import "../sass/layout";
-@import "../sass/report_list_pins";
body, body a {
font-family:"Trebuchet MS",Arial, Helvetica, sans-serif;
@@ -231,20 +230,14 @@ body.mappage {
background-color: #deead2;
}
-.item-list--reports {
- li:after {
- background-color: $oxfordshire_mid_grey_green;
- }
-
- h3 {
- color: $oxfordshire_link_colour;
- }
+.item-list--reports h3 {
+ color: $oxfordshire_link_colour;
}
h4.static-with-rule {
margin-top: 1em; // down from default 2em, avoid extra space between heading and .council_info_box
margin-bottom: 0; // no space between this and the .item-list items
- background: transparent; // rather than light grey
+ // TODO background: transparent; // rather than light grey
padding: 0.75em 1em * (1/0.875); // compensate for 0.875 font-size
}
diff --git a/web/cobrands/sass/_base.scss b/web/cobrands/sass/_base.scss
index 93e3cf201..179168aae 100644
--- a/web/cobrands/sass/_base.scss
+++ b/web/cobrands/sass/_base.scss
@@ -767,7 +767,9 @@ input.final-submit {
}
.btn--navigate,
-.btn--geolocate {
+.btn--geolocate,
+.btn--shortlist,
+.btn--shortlisted {
&:before {
content: "";
display: inline-block;
@@ -779,7 +781,7 @@ input.final-submit {
vertical-align: -0.1em; // vertically centre icon in button
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
- background-image: url(/cobrands/fixmystreet/images/navigate@2.png);
+ background-image: url(/cobrands/fixmystreet/images/navigate@2x.png);
}
@media all {
@@ -793,7 +795,7 @@ input.final-submit {
background-image: url(/cobrands/fixmystreet/images/crosshairs.png);
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
- background-image: url(/cobrands/fixmystreet/images/crosshairs@2.png);
+ background-image: url(/cobrands/fixmystreet/images/crosshairs@2x.png);
}
@media all {
@@ -802,6 +804,34 @@ input.final-submit {
}
}
+.btn--shortlist {
+ &:before {
+ background-image: url(/cobrands/fixmystreet/images/icon-shortlist-mini.png);
+
+ @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ background-image: url(/cobrands/fixmystreet/images/icon-shortlist-mini@2x.png);
+ }
+
+ @media all {
+ background-image: url(/cobrands/fixmystreet/images/icon-shortlist-mini.svg), none;
+ }
+ }
+}
+
+.btn--shortlisted {
+ &:before {
+ background-image: url(/cobrands/fixmystreet/images/icon-shortlisted-mini.png);
+
+ @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ background-image: url(/cobrands/fixmystreet/images/icon-shortlisted-mini@2x.png);
+ }
+
+ @media all {
+ background-image: url(/cobrands/fixmystreet/images/icon-shortlisted-mini.svg), none;
+ }
+ }
+}
+
.btn--block {
display: block;
text-align: center;
@@ -1013,6 +1043,152 @@ input.final-submit {
}
}
+// A version where the normal padding of the list-item is tweaked to
+// make room for an icon or a button next to the report details.
+.item-list__item--indented {
+ position: relative;
+ margin: 0; // reset 0.25em margin-top on default item-list__item
+ padding: 0;
+ border-top: 1px solid #e5e5e5; // can't apply border to `a` because of border-left
+
+ a {
+ display: block;
+ padding: 1em;
+ padding-#{$left}: 2.5em; // make space for background image
+ border-#{$left}: solid 1em transparent; // inset background image 1em from the left
+ background: transparent;
+ }
+
+ // Trigger hover style even when hovering over sibling item-action-button
+ &:hover a {
+ background-color: $itemlist_item_background_hover;
+ }
+
+ h3 {
+ color: inherit; // Some cobrands might want to override with $primary for a more colourful list
+ margin: 0 0 0.2em 0;
+ padding-top: 0; // override .item-list__heading
+ line-height: 1.3em; // override .item-list__heading
+ }
+
+ p {
+ margin: 0;
+ font-size: 0.8em;
+ color: #777;
+ }
+}
+
+// Add this to your .item-list__item--indented element if you
+// need to display both an action button *and* up/down arrows
+.item-list__item--act-and-sort {
+ a {
+ padding-#{$left}: 4.5em; // make space for the extra buttons
+ }
+
+ .item-list__item__shortlist-up,
+ .item-list__item__shortlist-down {
+ width: 36px; // down from 48px
+ left: 3.5em; // up from 1em
+ }
+}
+
+%list-item-action-button {
+ position: absolute;
+ left: 1em; // match the padding on the `a` element
+ top: 50%;
+ margin-top: -24px; // vertically center
+ margin-left: -12px; // horizontally center
+
+ display: block;
+ width: 48px;
+ font-size: 1em;
+
+ padding: 0;
+ border: none;
+ background: transparent;
+
+ overflow: hidden; // hide button text
+ height: 0;
+ padding-top: 48px;
+
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: 24px 24px;
+}
+
+.item-list__item__shortlist-add {
+ @extend %list-item-action-button;
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-inactive');
+
+ &:hover,
+ &:focus {
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-inactive-hover');
+ }
+}
+
+.item-list__item__shortlist-remove {
+ @extend %list-item-action-button;
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-active');
+
+ &:hover,
+ &:focus {
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-active-hover');
+ }
+}
+
+.item-list__item__shortlist-take {
+ @extend %list-item-action-button;
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-taken');
+
+ &:hover,
+ &:focus {
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-taken-hover');
+ }
+}
+
+.item-list__item__shortlist-up {
+ @extend %list-item-action-button;
+
+ padding-top: 24px; // half the normal height, because shorter icon
+ background-size: 24px 14px;
+
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-up');
+
+ &:hover,
+ &:focus {
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-up-hover');
+ }
+
+ &[disabled] {
+ opacity: 0.5;
+ cursor: default;
+
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-up');
+ }
+}
+
+.item-list__item__shortlist-down {
+ @extend %list-item-action-button;
+
+ margin-top: 0; // this is the "lower" arrow, so no need to offset vertical position
+ padding-top: 24px; // half the normal height, because shorter icon
+ background-size: 24px 14px;
+
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-down');
+
+ &:hover,
+ &:focus {
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-down-hover');
+ }
+
+ &[disabled] {
+ opacity: 0.5;
+ cursor: default;
+
+ @include high-dpi-background-image('/cobrands/fixmystreet/images/icon-shortlist-down');
+ }
+}
+
.item-list__heading {
font-size: 1em;
font-weight: normal;
@@ -1033,12 +1209,35 @@ input.final-submit {
}
}
-.item-list__item--empty p {
- margin: 0;
+.item-list__item__state {
+ font-size: 0.9em;
+ font-style: normal;
+ font-weight: bold;
+ padding: 0.2em 0.5em;
+ vertical-align: -0.1em;
+ background: #888;
+ color: #fff;
+ border-radius: 0.3em;
+ margin-right: 0.1em;
+}
+
+.item-list__item--empty {
+ background: none;
+ color: #777;
+
+ p {
+ margin: 0;
+ padding: 1em;
+ text-align: center;
+ }
}
.item-list--front-page {
border-bottom: none;
+
+ .item-list__item {
+ background-color: transparent;
+ }
}
.problem-header .update-img,
diff --git a/web/cobrands/sass/_layout.scss b/web/cobrands/sass/_layout.scss
index 48fdf32c0..a390a4131 100644
--- a/web/cobrands/sass/_layout.scss
+++ b/web/cobrands/sass/_layout.scss
@@ -617,6 +617,7 @@ body.authpage {
display:table;
width:100%;
padding: 0 0 1em;
+ table-layout: fixed;
>div {
display:table-cell;
width:50%;
diff --git a/web/cobrands/sass/_mixins.scss b/web/cobrands/sass/_mixins.scss
index 2b05b3c21..8b6114aec 100644
--- a/web/cobrands/sass/_mixins.scss
+++ b/web/cobrands/sass/_mixins.scss
@@ -171,3 +171,15 @@ $right: right;
-ms-flex-align: $alignment;
align-items: $alignment;
}
+
+@mixin high-dpi-background-image($path) {
+ background-image: url("#{$path}.png");
+
+ @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ background-image: url("#{$path}@2x.png");
+ }
+
+ @media screen {
+ background-image: url("#{$path}.svg"), none;
+ }
+}
diff --git a/web/cobrands/sass/_report_list_pins.scss b/web/cobrands/sass/_report_list_pins.scss
index eaeefbc10..3dae2cf84 100644
--- a/web/cobrands/sass/_report_list_pins.scss
+++ b/web/cobrands/sass/_report_list_pins.scss
@@ -1,15 +1,11 @@
+// Like .item-list__item--indented except with a pin icon baked in!
.item-list__item--with-pin {
- position: relative;
- margin: 0;
- padding: 0;
- background: none;
+ @extend .item-list__item--indented;
a {
- display: block;
- padding: 1em;
- padding-#{$left}: 3em;
- border-#{$left}: solid 1em transparent;
- background: transparent url(/i/pin-yellow-small.png) no-repeat $left center;
+ background-image: url(/i/pin-yellow-small.png);
+ background-repeat: no-repeat;
+ background-position: $left center;
}
&.yellow a {
@@ -24,31 +20,6 @@
&.grey a {
background-image: url(/i/pin-grey-small.png);
}
-
- &:after {
- content: "";
- display: block;
- height: 1px;
- position: absolute;
- #{$left}: 3em;
- #{$right}: 0;
- bottom: 0;
- background-color: #e5e5e5;
- }
-
- h3, p {
- margin: 0;
- }
-
- h3 {
- color: $primary;
- margin-bottom: 0.2em;
- }
-
- p {
- font-size: 0.8em;
- color: #777;
- }
}
.item-list--reports__item--selected {
background: $base_bg;
@@ -59,24 +30,6 @@
}
-.item-list__item--empty {
- background: none;
- color: #777;
- p {
- padding: 1em;
- text-align: center;
- }
-}
-
-/* We have no padding on the front page */
-body.frontpage {
- .item-list__item--with-pin a {
- padding: 0;
- padding-#{$left}: 3em;
- }
-}
-
-
.big-green-banner {
display: none; // hide the empty banner by default
}