aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZarino Zappia <mail@zarino.co.uk>2019-02-15 16:40:18 +0000
committerMatthew Somerville <matthew-github@dracos.co.uk>2019-02-25 12:18:59 +0000
commit3de73ad628759ca510012d532cc681e0b9008969 (patch)
treee56c13d9faa6aed097a88d422ca2a96270adcf84
parent30695f4dba18b2c476babf0f3bf1f4a79a099923 (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.html35
-rw-r--r--templates/web/base/report/_item_expandable.html55
-rw-r--r--templates/web/base/report/_item_small.html32
-rw-r--r--web/cobrands/fixmystreet/fixmystreet.js26
-rw-r--r--web/cobrands/sass/_base.scss73
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;