diff options
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Default.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/User.pm | 2 | ||||
-rw-r--r-- | t/app/controller/my_planned.t | 10 | ||||
-rw-r--r-- | templates/web/base/my/planned.html | 6 | ||||
-rw-r--r-- | templates/web/base/questionnaire/index.html | 20 | ||||
-rw-r--r-- | templates/web/base/report/_main.html | 64 | ||||
-rw-r--r-- | templates/web/fixmystreet.com/report/new/extra_name.html | 2 | ||||
-rw-r--r-- | templates/web/oxfordshire/header.html | 2 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/fixmystreet.js | 21 | ||||
-rw-r--r-- | web/cobrands/sass/_base.scss | 81 |
10 files changed, 134 insertions, 76 deletions
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index 47e577372..b6d03621f 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -717,7 +717,7 @@ sub available_permissions { report_edit_priority => _("Edit report priority"), # future use report_inspect => _("Markup problem details"), report_instruct => _("Instruct contractors to fix problems"), # future use - planned_reports => _("Manage planned reports list"), + planned_reports => _("Manage shortlist"), contribute_as_another_user => _("Create reports/updates on a user's behalf"), contribute_as_body => _("Create reports/updates as the council"), }, diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm index 0ba7e252c..363bbb930 100644 --- a/perllib/FixMyStreet/DB/Result/User.pm +++ b/perllib/FixMyStreet/DB/Result/User.pm @@ -327,7 +327,7 @@ sub adopt { $other->delete; } -# Planned reports +# Planned reports / shortlist # Override the default auto-created function as we only want one live entry per user around add_to_planned_reports => sub { diff --git a/t/app/controller/my_planned.t b/t/app/controller/my_planned.t index 25f82224e..7bd1dd2cd 100644 --- a/t/app/controller/my_planned.t +++ b/t/app/controller/my_planned.t @@ -13,8 +13,8 @@ my $body = $mech->create_body_ok(2237, 'Oxfordshire'); my ($problem) = $mech->create_problems_for_body(1, $body->id, 'Test Title'); $mech->get_ok($problem->url); -$mech->content_lacks('Add to planned reports'); -$mech->content_lacks('Remove from planned reports'); +$mech->content_lacks('Shortlist'); +$mech->content_lacks('Shortlisted'); my $user = $mech->log_in_ok( 'test@example.com' ); $user->update({ from_body => $body }); @@ -39,11 +39,11 @@ $mech->get_ok('/my/planned'); $mech->content_contains('Test Title'); $mech->get_ok($problem->url); -$mech->content_contains('Remove from planned reports'); +$mech->content_contains('Shortlisted'); $mech->submit_form_ok({ with_fields => { change => 'remove' } }); -$mech->content_contains('Add to planned reports'); +$mech->content_contains('Shortlist'); $mech->submit_form_ok({ with_fields => { change => 'add' } }); -$mech->content_contains('Remove from planned reports'); +$mech->content_contains('Shortlisted'); done_testing(); diff --git a/templates/web/base/my/planned.html b/templates/web/base/my/planned.html index 2e852ea01..19d29f970 100644 --- a/templates/web/base/my/planned.html +++ b/templates/web/base/my/planned.html @@ -1,7 +1,7 @@ [% SET bodyclass = 'mappage'; PROCESS "maps/${map.type}.html" IF problems.size; - INCLUDE 'header.html', title = loc('Your planned reports') + INCLUDE 'header.html', title = loc('Your shortlist') %] [% IF problems.size %] @@ -14,10 +14,10 @@ <div id="skipped-map"> [% END %] -<h1>[% loc('Your planned reports') %]</h1> +<h1>[% loc('Your shortlist') %]</h1> [% IF ! has_content %] -[% loc('You haven’t planned any reports yet.') %] +[% loc('You haven’t shortlisted any reports yet.') %] [% END %] <section class="full-width"> diff --git a/templates/web/base/questionnaire/index.html b/templates/web/base/questionnaire/index.html index 52d5ed5b1..7a7e433a1 100644 --- a/templates/web/base/questionnaire/index.html +++ b/templates/web/base/questionnaire/index.html @@ -48,22 +48,22 @@ [% loc('Has this problem been fixed?') %] </p> -<p class="radio-segmented-control"> +<p class="segmented-control segmented-control--radio"> <input type="radio" name="been_fixed" id="been_fixed_yes" value="Yes"[% ' checked' IF been_fixed == 'Yes' %]> - <label class="inline" for="been_fixed_yes">[% loc('Yes') %]</label> + <label for="been_fixed_yes">[% loc('Yes') %]</label> <input type="radio" name="been_fixed" id="been_fixed_no" value="No"[% ' checked' IF been_fixed == 'No' %]> - <label class="inline" for="been_fixed_no">[% loc('No') %]</label> + <label for="been_fixed_no">[% loc('No') %]</label> <input type="radio" name="been_fixed" id="been_fixed_unknown" value="Unknown"[% ' checked' IF been_fixed == 'Unknown' %]> - <label class="inline" for="been_fixed_unknown">[% loc('Don’t know') %]</label> + <label for="been_fixed_unknown">[% loc('Don’t know') %]</label> </p> [% UNLESS answered_ever_reported %] <p>[% loc('Have you ever reported a problem to a council before, or is this your first time?') %]</p> -<p class="radio-segmented-control"> +<p class="segmented-control segmented-control--radio"> <input type="radio" name="reported" id="reported_yes" value="Yes"[% ' checked' IF reported == 'Yes' %]> - <label class="inline" for="reported_yes">[% loc('Reported before') %]</label> + <label for="reported_yes">[% loc('Reported before') %]</label> <input type="radio" name="reported" id="reported_no" value="No"[% ' checked' IF reported == 'No' %]> - <label class="inline" for="reported_no">[% loc('First time') %]</label> + <label for="reported_no">[% loc('First time') %]</label> </p> [% END %] @@ -99,11 +99,11 @@ <div class="js-another-questionnaire"> <p>[% loc('Would you like to receive another questionnaire in 4 weeks, reminding you to check the status?') %]</p> - <p class="radio-segmented-control"> + <p class="segmented-control segmented-control--radio"> <input type="radio" name="another" id="another_yes" value="Yes"[% ' checked' IF another == 'Yes' %]> - <label class="inline" for="another_yes">[% loc('Yes') %]</label> + <label for="another_yes">[% loc('Yes') %]</label> <input type="radio" name="another" id="another_no" value="No"[% ' checked' IF another == 'No' %]> - <label class="inline" for="another_no">[% loc('No') %]</label> + <label for="another_no">[% loc('No') %]</label> </p> </div> diff --git a/templates/web/base/report/_main.html b/templates/web/base/report/_main.html index e02d4b2b0..e475eb3aa 100644 --- a/templates/web/base/report/_main.html +++ b/templates/web/base/report/_main.html @@ -8,19 +8,25 @@ <div class="problem-header clearfix" problem-id="[% problem.id %]"> [% IF c.user.has_permission_to('planned_reports', problem.bodies_str) %] -<form method="post" action="/my/planned/change" id="planned_form"> +<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 %]"> - <p><input type="submit" - data-remove="[% loc('Remove from planned reports') %]" data-add="[% loc('Add to planned reports') %]" - value=" + <p><input + type="submit" + id="shortlist-report" + data-label-remove="[% loc('Remove from shortlist') %]" + data-label-add="[% loc('Add to shortlist') %]" + data-value-remove="[% loc('Shortlisted') %]" + data-value-add="[% loc('Shortlist') %]" [%~ IF c.user.is_planned_report(problem) ~%] - [% loc('Remove from planned reports') %] + value="[% loc('Shortlisted') %]" + aria-label="[% loc('Remove from shortlist') %]" [%~ ELSE ~%] - [% loc('Add to planned reports') %] + value="[% loc('Shortlist') %]" + aria-label="[% loc('Add to shortlist') %]" [%~ END ~%] - "></p> + ></p> </form> [% END %] @@ -106,25 +112,39 @@ </div> [% END %] - [% IF permissions.keys.grep('moderate|report_inspect|report_edit_category|report_edit_priority').size %] - <p class="moderate-display"> + [% IF permissions.moderate %] + </form> + [% END %] + + [% IF + (permissions.moderate) + OR + (!hide_inspect_button AND + permissions.keys.grep('report_inspect|report_edit_category|report_edit_priority').size) + OR + (c.user.has_permission_to('planned_reports', problem.bodies_str)) + %] + <div class="moderate-display segmented-control" role="menu"> [% IF permissions.moderate %] - <input type="button" class="btn moderate" value="Moderate this report"> + <a id="moderate-report" role="menuitem" aria-label="[% loc('Moderate this report') %]">[% loc('Moderate') %]</a> [% END %] [% IF !hide_inspect_button AND permissions.keys.grep('report_inspect|report_edit_category|report_edit_priority').size %] - <a href="/report/[% problem.id %]/inspect" class="btn inspect"> - [%- IF permissions.report_inspect %] - [%- loc('Inspect') %] - [%- ELSE %] - [%- loc('Manage') %] - [%- END ~%] - </a> + <a href="/report/[% problem.id %]/inspect" role="menuitem"> + [%~ IF permissions.report_inspect ~%] + [%~ loc('Inspect') ~%] + [%~ ELSE ~%] + [%~ loc('Manage') ~%] + [%~ END ~%] + </a> [% END %] - </p> - [% END %] - - [% IF permissions.moderate %] - </form> + [% IF c.user.has_permission_to('planned_reports', problem.bodies_str) %] + [%~ IF c.user.is_planned_report(problem) ~%] + <label for="shortlist-report" role="menuitem" aria-label="[% loc('Remove from shortlist') %]">[% loc('Shortlisted') %]</label> + [%~ ELSE ~%] + <label for="shortlist-report" role="menuitem" aria-label="[% loc('Add to shortlist') %]">[% loc('Shortlist') %]</label> + [%~ END ~%] + [% END %] + </div> [% END %] [% TRY %][% PROCESS 'report/_main_after.html' %][% CATCH file %][% END %] diff --git a/templates/web/fixmystreet.com/report/new/extra_name.html b/templates/web/fixmystreet.com/report/new/extra_name.html index 80ab1837a..f329541c3 100644 --- a/templates/web/fixmystreet.com/report/new/extra_name.html +++ b/templates/web/fixmystreet.com/report/new/extra_name.html @@ -8,7 +8,7 @@ shared with the council or displayed publicly.</em> </p> [% SET gender = report.get_extra_metadata('gender') %] -<p class="radio-segmented-control" style="font-size: 80%"> +<p class="segmented-control segmented-control--radio" style="font-size: 80%"> <input type="radio" name="gender" id="gender_female" value="female"[% ' checked' IF gender == 'female' %]> <label for="gender_female">Female</label> <input type="radio" name="gender" id="gender_male" value="male"[% ' checked' IF gender == 'male' %]> diff --git a/templates/web/oxfordshire/header.html b/templates/web/oxfordshire/header.html index d5884272b..5b5532b67 100644 --- a/templates/web/oxfordshire/header.html +++ b/templates/web/oxfordshire/header.html @@ -45,7 +45,7 @@ [% IF c.user_exists AND c.user.has_body_permission_to('planned_reports') %] <li> <[% IF c.req.uri.path == '/my/planned' %]span[% ELSE %]a href="/my/planned"[% END - %]>[% loc('Planned reports') %]</[% c.req.uri.path == '/my/planned' ? 'span' : 'a' %]> + %]>[% loc('Shortlist') %]</[% c.req.uri.path == '/my/planned' ? 'span' : 'a' %]> </li> [% END %] <li> diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index b6f92b6d6..d6e967bc3 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -281,16 +281,25 @@ $.extend(fixmystreet.set_up, { var $form = $(this), $change = $form.find("input[name='change']" ), $submit = $form.find("input[type='submit']" ), - data = $form.serialize() + '&ajax=1'; + $labels = $('label[for="' + $submit.attr('id') + '"]'), + data = $form.serialize() + '&ajax=1', + changeValue, + buttonLabel, + buttonValue; $.post(this.action, data, function(data) { if (data.outcome == 'add') { - $change.val('remove'); - $submit.val($submit.data('remove')); + changeValue = "remove"; + buttonLabel = $submit.data('label-remove'); + buttonValue = $submit.data('value-remove'); } else if (data.outcome == 'remove') { - $change.val('add'); - $submit.val($submit.data('add')); + changeValue = "add"; + buttonLabel = $submit.data('label-add'); + buttonValue = $submit.data('value-add'); } + $change.val(changeValue); + $submit.val(buttonValue).attr('aria-label', buttonLabel); + $labels.text(buttonValue).attr('aria-label', buttonLabel); }); }); }, @@ -791,7 +800,7 @@ $.extend(fixmystreet.set_up, { function add_handlers (elem, word) { elem.each( function () { var $elem = $(this); - $elem.find('.moderate').click( function () { + $elem.find('#moderate-report').on('click', function () { $elem.find('.moderate-display').hide(); $elem.find('.moderate-edit').show(); }); diff --git a/web/cobrands/sass/_base.scss b/web/cobrands/sass/_base.scss index d1fdec343..8760eba97 100644 --- a/web/cobrands/sass/_base.scss +++ b/web/cobrands/sass/_base.scss @@ -1033,6 +1033,11 @@ input.final-submit { .problem-header { margin-bottom: 1em; + + // Clear the admin actions after the floated photo(s). + .segmented-control { + clear: both; + } } .report_meta_info, @@ -1773,41 +1778,49 @@ table.nicetable { margin-left: 0; } -.radio-segmented-control { - overflow: auto; // clear floats (if browser doesn't support flexbox) +.segmented-control { + @include clearfix(); display: flex; // fancy full-width buttons for browsers that support flexbox - input { - position: absolute; - left: -999px; - } - - label { + & > * { display: block; margin: 0; - padding: 0.75em 1.5em; + padding: 0.75em 0.5em; text-align: center; background: #fff linear-gradient(to bottom, #fff 0%, #eee 100%) 0 0 no-repeat; - border: 1px solid #ddd; + border: 1px solid #ccc; border-right-width: 0; // avoid double border between items font-weight: bold; + color: inherit !important; + text-decoration: none !important; + cursor: pointer; float: left; // float fallback for browsers that don't support flexbox flex: 1 0 auto; - @media(max-width: 400px){ - // Shameful hack to stop the control expanding wider than the window - // on narrow devices (eg: 320px iPhone), which would cause horizontal - // scrolling, and clipped text on the new report page, for example. - // Flexbox will add the spacing back in anyway. Ideally we'd only apply - // this style if flexbox is supported, but there's no easy way to do that. - padding: 0.75em 0; - } - - &:hover, &:focus { + &:hover { background: #f3f3f3 linear-gradient(to bottom, #f9f9f9 0%, #e9e9e9 100%) 0 0 no-repeat; } } + & > :first-child { + border-radius: 0.25em 0 0 0.25em; + } + + & > :last-child { + border-radius: 0 0.25em 0.25em 0; + border-right-width: 1px; // reinstate border on last item + } +} + +// A special case of segmented control, where each "button" (or label) is +// preceded by a radio button, which needs to be hidden but interactive. +// Checked checkboxes give their following label a "pressed" appearance. +.segmented-control--radio { + input { + position: absolute; + left: -999px; + } + input:checked + label { color: $primary_text; background: $primary; @@ -1818,17 +1831,14 @@ table.nicetable { } input:checked + label + input + label { - border-left-width: none; // in favour of the realistic coloured border on the selected item + border-left-width: 0; // in favour of the realistic coloured border on the selected label } + // The first label is no longer the first child, so we need to + // fish it out specially with a next sibling selector. input:first-child + label { border-radius: 0.25em 0 0 0.25em; } - - label:last-child { - border-radius: 0 0.25em 0.25em 0; - border-right-width: 1px; // reinstate border on last item - } } .my-account-buttons a { @@ -1838,6 +1848,25 @@ table.nicetable { border-radius: 0.2em; } +// Useful for inserting hidden forms on the page, but still allowing +// inputs inside the form to be toggled by labels outside the form. +// Try using this in combination with .segmented-control for funtimes. +.hidden-label-target { + position: absolute; + top: -100px; + width: 0; + height: 0; + overflow: hidden; + opacity: 0; + + // Tell assistive devices to ignore this element. + visibility: hidden; + + // Hack for IE8 which doesn't allow interaction with + // `visibility:hidden` elements. + visibility: visible\9; +} + @media screen { .print-only { |