aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZarino Zappia <mail@zarino.co.uk>2016-09-19 17:07:45 +0100
committerMatthew Somerville <matthew@mysociety.org>2016-09-20 15:10:52 +0100
commitac8145c7ec2d648be0c687d2d0037757f4142eaf (patch)
treeb4461616a580ab09529cd4983991d6da314b49a3
parente9a5d2fb6e1985a0d946ad3574234784f4f659c4 (diff)
Organize report admin actions into single control.
As part of this, rename "planned reports" to "shortlist". The `.segmented-control` component now supports basic usage (as in the admin report actions menu bar) and usage with hidden radio inputs and labels (as on the report questionnaire page).
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm2
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm2
-rw-r--r--t/app/controller/my_planned.t10
-rw-r--r--templates/web/base/my/planned.html6
-rw-r--r--templates/web/base/questionnaire/index.html20
-rw-r--r--templates/web/base/report/_main.html64
-rw-r--r--templates/web/fixmystreet.com/report/new/extra_name.html2
-rw-r--r--templates/web/oxfordshire/header.html2
-rw-r--r--web/cobrands/fixmystreet/fixmystreet.js21
-rw-r--r--web/cobrands/sass/_base.scss81
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&rsquo;t planned any reports yet.') %]
+[% loc('You haven&rsquo;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&rsquo;t know') %]</label>
+ <label for="been_fixed_unknown">[% loc('Don&rsquo;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 {