diff options
author | Zarino Zappia <mail@zarino.co.uk> | 2019-02-15 16:40:18 +0000 |
---|---|---|
committer | Matthew Somerville <matthew-github@dracos.co.uk> | 2019-02-25 12:18:59 +0000 |
commit | 3de73ad628759ca510012d532cc681e0b9008969 (patch) | |
tree | e56c13d9faa6aed097a88d422ca2a96270adcf84 | |
parent | 30695f4dba18b2c476babf0f3bf1f4a79a099923 (diff) |
Expandable list item component
`_item_expandable.html` is an alternative to regular list items, where
you can display extra information on the first click on the item, and
then also, optionally, offer a further action, as a separate button.
Right now the expandable list items aren’t used anywhere, but we’ll
soon be using them in the duplicate report suggestion UI for council
staff and the public.
-rw-r--r-- | templates/web/base/report/_item.html | 35 | ||||
-rw-r--r-- | templates/web/base/report/_item_expandable.html | 55 | ||||
-rw-r--r-- | templates/web/base/report/_item_small.html | 32 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/fixmystreet.js | 26 | ||||
-rw-r--r-- | web/cobrands/sass/_base.scss | 73 |
5 files changed, 186 insertions, 35 deletions
diff --git a/templates/web/base/report/_item.html b/templates/web/base/report/_item.html index d710f6c81..863b87817 100644 --- a/templates/web/base/report/_item.html +++ b/templates/web/base/report/_item.html @@ -42,40 +42,7 @@ [% IF c.user.has_permission_to('report_inspect', problem.bodies_str_ids) %] <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">[% prettify_state('fixed') %]</span> - [% ELSIF NOT no_fixed AND problem.is_closed %] - <span class="item-list__item__state">[% prettify_state('closed') %]</span> - [% ELSIF (c.user.has_permission_to('report_edit_priority', problem.bodies_str_ids) OR c.user.has_permission_to('report_inspect', problem.bodies_str_ids)) AND problem.response_priority %] - <span class="item-list__item__state">[% problem.response_priority.name %]</span> - [% END %] - [%- IF c.cobrand.moniker != 'fixamingata' %] [%# Default: %] - [%- IF problem.days_ago > 0 AND problem.days_ago <= c.cobrand.display_days_ago_threshold %] - [% tprintf( nget('Reported %d day ago', 'Reported %d days ago', problem.days_ago), problem.days_ago ) %] - [%- ELSE %] - [% prettify_dt( problem.confirmed, 1 ) %] - [%- END %] - [%- ELSE %] [%# Swedish cobrand fixamingata: %] - [%- prettify_dt( problem.confirmed) %] - [%- END %] - [%- IF dist %], [% dist %]km[% END %] - [%- IF problem.confirmed != problem.lastupdate AND problem.whensent != problem.lastupdate %], - [%- IF problem.days_ago('lastupdate') > 0 AND problem.days_ago('lastupdate') <= c.cobrand.display_days_ago_threshold %] - [% tprintf( nget('last updated %d day ago', 'last updated %d days ago', problem.days_ago('lastupdate') ), problem.days_ago('lastupdate') ) %] - [%- ELSE %] - [% tprintf(loc('last updated %s'), prettify_dt( problem.lastupdate, 1 ) ) %] - [%- END %] - [%- END %] - [% IF include_sentinfo %] - [% IF c.cobrand.is_council && !c.cobrand.owns_problem( problem ) %] - (sent to [% problem.body %]) - [% ELSIF problem.bodies_str_ids.size > 2 %] [% loc('(sent to all)') %] - [% ELSIF problem.bodies_str_ids.size == 2 %] [% loc('(sent to both)') %] - [% ELSIF problem.bodies_str_ids.size == 0 %] [% loc('(not sent to council)') %] - [% END %] - [% END %] - </small> + <small>[% PROCESS 'report/_item_small.html' %]</small> [% IF c.user.has_permission_to('report_inspect', problem.bodies_str_ids) %] <div class="item-list__item__metadata"> diff --git a/templates/web/base/report/_item_expandable.html b/templates/web/base/report/_item_expandable.html new file mode 100644 index 000000000..6a4fe7191 --- /dev/null +++ b/templates/web/base/report/_item_expandable.html @@ -0,0 +1,55 @@ +[%# + This list item contains a full photo set and description, which is hidden + until the `.expanded` class is added. It is useful for times when you want + to surface the full information about a report, without requiring the user + to visit the dedicated report page. + + Since the photo set includes `<a>` elements of its own, we drop the usual + "wrapper" `<a>` and the associated `.item-list--reports__item` class, to + avoid anchor nesting. +%] + +[% truncated_detail = BLOCK %][% problem.detail | truncate(75, '…') | html_para %][% END ~%] +[% full_detail = BLOCK %][% problem.detail | add_links | html_para %][% END ~%] +[% SET show_more = truncated_detail != full_detail OR problem.photo ~%] + +<li class="[% 'js-expandable ' IF show_more %]item-list__item item-list__item--expandable [% item_extra_class %]" + data-report-id="[% problem.id | html %]" + id="report-[% problem.id | html %]"> + + [% IF problem.photo %] + <a href="[% c.cobrand.base_url_for_report( problem ) %][% problem.url %]" class="item-list__item--expandable__hide-when-expanded"> + <img class="img" height="60" width="90" src="[% problem.photos.first.url_fp %]" alt=""> + </a> + [% END %] + + [% TRY %] + [% PROCESS 'report/_item_heading.html' %] + [% CATCH file %] + <h3> + <a href="[% c.cobrand.base_url_for_report( problem ) %][% problem.url %]"> + [% problem.title | html %] + </a> + </h3> + [% END %] + + <small>[% PROCESS 'report/_item_small.html' %]</small> + + <div class="item-list__item--expandable__hide-when-expanded"> + [% truncated_detail %] + </div> + + [% IF show_more ~%] + <div class="item-list__item--expandable__hide-until-expanded"> + [% full_detail %] + [% INCLUDE 'report/photo.html' object=problem %] + </div> + [% END %] + + <div class="item-list__item--expandable__actions"> + [% IF show_more ~%] + <button class="btn btn--small js-toggle-expansion" data-more="[% loc('Read more') %]" data-less="[% loc('Read less') %]">[% loc('Read more') %]</button> + [% END %] + </div> + +</li> diff --git a/templates/web/base/report/_item_small.html b/templates/web/base/report/_item_small.html new file mode 100644 index 000000000..77fc9f569 --- /dev/null +++ b/templates/web/base/report/_item_small.html @@ -0,0 +1,32 @@ +[% IF NOT no_fixed AND problem.is_fixed %] + <span class="item-list__item__state">[% prettify_state('fixed') %]</span> +[% ELSIF NOT no_fixed AND problem.is_closed %] + <span class="item-list__item__state">[% prettify_state('closed') %]</span> +[% ELSIF (c.user.has_permission_to('report_edit_priority', problem.bodies_str_ids) OR c.user.has_permission_to('report_inspect', problem.bodies_str_ids)) AND problem.response_priority %] + <span class="item-list__item__state">[% problem.response_priority.name %]</span> +[% END %] +[%- IF c.cobrand.moniker != 'fixamingata' %] [%# Default: %] + [%- IF problem.days_ago > 0 AND problem.days_ago <= c.cobrand.display_days_ago_threshold %] + [% tprintf( nget('Reported %d day ago', 'Reported %d days ago', problem.days_ago), problem.days_ago ) %] + [%- ELSE %] + [% prettify_dt( problem.confirmed, 1 ) %] + [%- END %] +[%- ELSE %] [%# Swedish cobrand fixamingata: %] + [%- prettify_dt( problem.confirmed) %] +[%- END %] +[%- IF dist %], [% dist %]km[% END %] +[%- IF problem.confirmed != problem.lastupdate AND problem.whensent != problem.lastupdate %], + [%- IF problem.days_ago('lastupdate') > 0 AND problem.days_ago('lastupdate') <= c.cobrand.display_days_ago_threshold %] + [% tprintf( nget('last updated %d day ago', 'last updated %d days ago', problem.days_ago('lastupdate') ), problem.days_ago('lastupdate') ) %] + [%- ELSE %] + [% tprintf(loc('last updated %s'), prettify_dt( problem.lastupdate, 1 ) ) %] + [%- END %] +[%- END %] +[% IF include_sentinfo %] + [% IF c.cobrand.is_council && !c.cobrand.owns_problem( problem ) %] + (sent to [% problem.body %]) + [% ELSIF problem.bodies_str_ids.size > 2 %] [% loc('(sent to all)') %] + [% ELSIF problem.bodies_str_ids.size == 2 %] [% loc('(sent to both)') %] + [% ELSIF problem.bodies_str_ids.size == 0 %] [% loc('(not sent to council)') %] + [% END %] +[% END %] diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index 5efc0d878..bbcf73055 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -1049,6 +1049,32 @@ $.extend(fixmystreet.set_up, { var set_map_state = true; fixmystreet.back_to_reports_list(e, report_list_url, map_state, set_map_state); }); + }, + + expandable_list_items: function(){ + $(document).on('click', '.js-toggle-expansion', function(e) { + e.preventDefault(); // eg: prevent button from submitting parent form + var $toggle = $(this); + var $parent = $toggle.closest('.js-expandable'); + $parent.toggleClass('expanded'); + $toggle.text($parent.hasClass('expanded') ? $toggle.data('less') : $toggle.data('more')); + }); + + $(document).on('click', '.js-expandable', function(e) { + var $parent = $(this); + // Ignore parents that are already expanded. + if ( ! $parent.hasClass('expanded') ) { + // Ignore clicks on action buttons (clicks on the + // .js-toggle-expansion button will be handled by + // the more specific handler above). + if ( ! $(e.target).is('.item-list__item--expandable__actions *') ) { + e.preventDefault(); + $parent.addClass('expanded'); + var $toggle = $parent.find('.js-toggle-expansion'); + $toggle.text($toggle.data('less')); + } + } + }); } }); diff --git a/web/cobrands/sass/_base.scss b/web/cobrands/sass/_base.scss index 8348dfcd7..7937139a0 100644 --- a/web/cobrands/sass/_base.scss +++ b/web/cobrands/sass/_base.scss @@ -1199,7 +1199,8 @@ input.final-submit { background-color: rgba(255, 255, 255, 0.5); } - .item-list--reports__item--selected { + .item-list--reports__item--selected, + .js & .item-list--reports__item--selected.expanded:hover { border: 0.25em solid $primary; background-color: #fff; } @@ -1256,6 +1257,76 @@ input.final-submit { } } +.item-list__item--expandable { + @include clearfix(); + border-top: 1px solid #fff; + background-color: transparent; + margin: 0; + padding: 1em; + + .js & { + cursor: pointer; + + &:hover, &.hovered { + background-color: $itemlist_item_background_hover; + } + } + + h3 { + margin: 0; + } + + .img { + float: $right; + width: 90px; + height: auto; + margin: flip(0 0 0.5em 1em, 0 1em 0.5em 0); + } + + small { + color: #666; + display: block; + margin-top: 0.5em; + } + + p { + line-height: 1.4em; + margin-top: 0.5em; + } + + &.expanded { + .js & { + cursor: default; + + &:hover { + background-color: transparent; + } + } + } +} + +.item-list__item--expandable__actions { + @include flex-container(); + + & > * { + @include flex(1); // Force equal width children + } +} + +.item-list__item--expandable__hide-until-expanded { + display: none; + + .expanded & { + display: block; + } +} + +.item-list__item--expandable__hide-when-expanded { + .expanded & { + display: none; + } +} + .problem-header .update-img, .item-list .update-img { float: $right; |