Skip to content

Commit 09e7ecd

Browse files
pgrunewaldpetschki
authored andcommitted
feat(pat structure)!: Improve selection button and popover
The selection button shows now the number of selected and maximum number of items within the current folder. The corresponding popover offers the option to select all items, all visible items on the page and to cancel the selection. The previous popover to manage the selected items is gone. There are also some minor fixes, e.g. one to prevent degrading the breadcrumb to show only ids, but rather keep the titles. The upper-left checkbox in the table for selecting all the items has now a tooltip.
1 parent 570a7d7 commit 09e7ecd

File tree

8 files changed

+88
-98
lines changed

8 files changed

+88
-98
lines changed

src/pat/structure/js/views/app.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,11 @@ export default BaseView.extend({
105105

106106
this.wellView = new SelectionWellView({
107107
collection: this.selectedCollection,
108-
triggerView: this.toolbar.get("selected-items"),
108+
triggerView: this.toolbar.get("change-selection"),
109109
app: this,
110-
id: "selected-items",
110+
id: "change-selection",
111111
});
112112

113-
this.toolbar.get("selected-items").disable();
114113
this.buttons.disable();
115114

116115
let timeout = 0;
@@ -241,10 +240,8 @@ export default BaseView.extend({
241240

242241
updateButtons: function () {
243242
if (this.selectedCollection.length) {
244-
this.toolbar.get("selected-items").enable();
245243
this.buttons.enable();
246244
} else {
247-
this.toolbar.get("selected-items").disable();
248245
this.buttons.disable();
249246
}
250247

@@ -409,10 +406,11 @@ export default BaseView.extend({
409406

410407
items.push(
411408
new SelectionButtonView({
412-
title: _t("Selected"),
413-
id: "selected-items",
409+
title: _t("${current} of ${total} selected", { current: 0, total: 0 }),
410+
id: "change-selection",
414411
tooltip: _t("Manage selection"),
415412
collection: this.selectedCollection,
413+
appCollection: this.collection,
416414
icon: "plone-selection",
417415
})
418416
);

src/pat/structure/js/views/selectionbutton.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import ButtonView from "../../../../core/ui/views/button";
2-
import tplButton from "../../templates/selection_button.xml";
32

43
export default ButtonView.extend({
54
collection: null,
6-
template: tplButton,
5+
template: '<%- _t("${current} of ${total} selected", { current: current, total: total }) %>',
76

87
initialize: function (options) {
98
ButtonView.prototype.initialize.apply(this, [options]);
@@ -26,15 +25,10 @@ export default ButtonView.extend({
2625
}
2726
},
2827

29-
serializedModel: function () {
30-
const obj = {
31-
icon: "",
32-
title: this.options.title,
33-
length: 0,
28+
serializedModel: function() {
29+
return {
30+
current: (this.collection !== null) ? this.collection.length : 0,
31+
total: (this.appCollection.state.totalRecords) ? this.appCollection.state.totalRecords : 0,
3432
};
35-
if (this.collection !== null) {
36-
obj.length = this.collection.length;
37-
}
38-
return obj;
3933
},
4034
});

src/pat/structure/js/views/selectionwell.js

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,26 @@ import _ from "underscore";
33
import PopoverView from "../../../../core/ui/views/popover";
44
import utils from "../../../../core/utils";
55
import ItemTemplate from "../../templates/selection_item.xml";
6+
import Actions from "../actions";
7+
import _t from "../../../../core/i18n-wrapper";
68

79
export default PopoverView.extend({
8-
className: "popover selected-items",
10+
className: "popover change-selection",
911

10-
title: _.template(
11-
'<input type="text" class="filter" placeholder="<%- _t("Filter") %>" />' +
12-
'<a href="#" class=" remove-all">' +
13-
'<%= removeIcon %> <%- _t("remove all") %></a>'
14-
),
12+
13+
title: _t("Change selection"),
1514

1615
content: _.template(
17-
"<% collection.each(function(item) { %>" +
18-
"<%= item_template($.extend({'removeIcon': removeIcon}, item.toJSON())) %>" +
19-
"<% }); %>"
16+
'<div class="list-group">' +
17+
'<a href="#" class="list-group-item list-group-item-action select-all"><%= selectAllIcon %> <%- _t("Select all items in the folder") %></a>' +
18+
'<a href="#" class="list-group-item list-group-item-action select-all-visible"><%= selectPageIcon %> <%- _t("Select all items on this page") %></a>' +
19+
'<a href="#" class="list-group-item list-group-item-action remove-all"><%= removeIcon %> <%- _t("Cancel selection") %></a>' +
20+
'</div>'
2021
),
2122

2223
events: {
23-
"click a.remove": "itemRemoved",
24-
"keyup input.filter": "filterSelected",
24+
"click .select-all": "selectAll",
25+
"click .select-all-visible": "selectVisible",
2526
"click .remove-all": "removeAll",
2627
},
2728

@@ -39,35 +40,33 @@ export default PopoverView.extend({
3940

4041
render: async function () {
4142
this.options["removeIcon"] = await utils.resolveIcon("x-circle");
43+
this.options["selectAllIcon"] = await utils.resolveIcon("check2-all");
44+
this.options["selectPageIcon"] = await utils.resolveIcon("check2");
4245
PopoverView.prototype.render.call(this);
4346
if (this.collection.length === 0) {
4447
this.$el.removeClass("active");
4548
}
4649
return this;
4750
},
48-
49-
itemRemoved: function (e) {
50-
e.preventDefault();
51-
const uid = $(e.currentTarget).data("uid");
52-
this.collection.removeByUID(uid);
53-
if (this.collection.length !== 0) {
54-
// re-rendering causes it to close, reopen
55-
this.show();
56-
}
51+
selectAll: function (e) {
52+
// use the actions module as it has a handy "selectAll" method
53+
const actions = new Actions({
54+
app: this.options.app,
55+
model: {
56+
attributes: this.options.app.options,
57+
},
58+
selectedCollection: this.options.collection,
59+
});
60+
actions.selectAll(e);
61+
this.options.app.tableView.setContextInfo();
62+
this.hide();
5763
},
58-
59-
filterSelected: function (e) {
60-
const val = $(e.target).val().toLowerCase();
61-
for (const item of $(".selected-item", this.$el)) {
62-
const $el = $(item);
63-
if ($el.text().toLowerCase().indexOf(val) === -1) {
64-
$el.hide();
65-
} else {
66-
$el.show();
67-
}
68-
}
64+
selectVisible: function (e) {
65+
e.preventDefault();
66+
this.collection.reset();
67+
$('input[type="checkbox"]', this.app.tableView.$('tbody')).prop('checked', true).change();
68+
this.hide();
6969
},
70-
7170
removeAll: function (e) {
7271
e.preventDefault();
7372
this.collection.reset();

src/pat/structure/js/views/table.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ export default BaseView.extend({
6868
this.trigger("context-info:set");
6969
},
7070

71-
render: async function () {
71+
/**
72+
* Render method
73+
* @param {any} triggerCollection – if render is called as callback for a Backbone collection, Backbone will
74+
* pass the collection as first argument
75+
*/
76+
render: async function (triggerCollection) {
7277
// By default do not start sorted by any column
7378
// Ignore first column and the last one (activeColumns.length + 1)
7479
// Do not show paginator, search or information, we only want column sorting
@@ -156,6 +161,14 @@ export default BaseView.extend({
156161
await table_row_rendering_finished();
157162
events.remove_event_listener = (this.el, "table_row_rendering_finished__listener"); // prettier-ignore
158163
registry.scan(this.$el);
164+
165+
// Set the context (again) after rerendering. If render was called after a collection sync – which is the
166+
// case if Backbone passed the collection as eventObject – do nothing, as collection syncs are always
167+
// followed by a context sync followed by a 'context-info-loaded' event,
168+
// which will trigger setContextInfo with the new context anyway.
169+
if (this.contextInfo && triggerCollection !== this.collection) {
170+
this.setContextInfo();
171+
}
159172
}
160173

161174
this.$el
@@ -231,6 +244,7 @@ export default BaseView.extend({
231244
},
232245

233246
selectAll: function (e) {
247+
// select all items on the *current* page
234248
if ($(e.target).is(":checked")) {
235249
$('input[type="checkbox"]', this.$("tbody")).prop("checked", true).trigger("change");
236250
} else {
@@ -242,12 +256,6 @@ export default BaseView.extend({
242256
}
243257
this.setContextInfo();
244258
},
245-
toggleSelectAll: function (e) {
246-
const $el = $(e.target);
247-
if (!$el.is(":checked")) {
248-
this.$(".select-all").prop("checked", false);
249-
}
250-
},
251259

252260
addReordering: function () {
253261
// if we have a custom query going on, we do not allow sorting.

src/pat/structure/structure.scss

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
margin-right: 1em;
4141
}
4242

43-
#btn-selected-items,
43+
#btn-change-selection,
4444
#btn-structure-rearrange,
4545
#btn-upload,
4646
#btn-filter {
@@ -292,38 +292,26 @@
292292
}
293293
}
294294

295-
.popover.selected-items {
295+
.popover.change-selection {
296296
--bs-popover-max-width: 350px;
297297

298-
.items {
299-
max-height: 300px;
300-
overflow-y: auto;
301-
302-
.selected-item {
303-
display: flex;
304-
margin: 0 8px 3px 0;
305-
border-radius: 6px;
306-
padding: 4px 6px;
307-
word-break: break-all;
308-
&:hover {
309-
background-color: var(--bs-light);
310-
}
311-
312-
a {
313-
padding-right:.5rem;
298+
.popover-content {
299+
padding: 0;
300+
}
314301

315-
&:hover {
316-
text-decoration: none;
317-
}
302+
.list-group-item:first-child {
303+
border-top-left-radius: unset;
304+
border-top-right-radius: unset;
305+
}
318306

319-
&:before {
320-
color: var(--bs-gray);
307+
a {
308+
svg {
309+
margin-right: calc(var(--bs-list-group-item-padding-x) * 0.5);
310+
display: inline-block;
311+
}
321312

322-
&:hover {
323-
color: var(--bs-gray-dark);
324-
}
325-
}
326-
}
313+
&:hover {
314+
text-decoration: none;
327315
}
328316
}
329317
}

src/pat/structure/templates/selection_button.xml

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/pat/structure/templates/table.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
data-pat-datatables="<%- datatables_options %>">
1919
<thead>
2020
<tr>
21-
<th class="selection"><label for="selectAllInputCheckbox" class="hiddenStructure" aria-label="<%- _t('Select all') %>"><%- _t('Select all') %></label><input id="selectAllInputCheckbox" type="checkbox" class="select-all form-check-input" /></th>
21+
<th class="selection"><label for="selectAllInputCheckbox" class="hiddenStructure" aria-label="<%- _t('Select all items on this page') %>"><%- _t('Select all items on this page') %></label><input id="selectAllInputCheckbox" type="checkbox" class="select-all form-check-input pat-tooltip" title="<%- _t('Select all items on this page') %>"/></th>
2222
<th class="title"><%- _t('Title') %></th>
2323
<% activeColumns.forEach((column, idx) => { %>
2424
<% if(column !== 'Description' && hasOwnProperty.call(availableColumns, column)) { %>

widgets.pot

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ msgid "Configure displayed columns"
290290
msgstr ""
291291

292292
#: ./src/pat/structure/js/views/app.js
293-
msgid "Selected"
293+
msgid "${current} of ${total} selected"
294294
msgstr ""
295295

296296
#: ./src/pat/structure/js/views/app.js
@@ -358,11 +358,19 @@ msgid "Sorting the content on the base of the site could affect your navigation
358358
msgstr ""
359359

360360
#: ./src/pat/structure/js/views/selectionwell.js
361-
msgid "Filter"
361+
msgid "Change selection"
362+
msgstr ""
363+
364+
#: ./src/pat/structure/js/views/selectionwell.js
365+
msgid "Select all items in the folder"
366+
msgstr ""
367+
368+
#: ./src/pat/structure/js/views/selectionwell.js
369+
msgid "Select all items on this page"
362370
msgstr ""
363371

364372
#: ./src/pat/structure/js/views/selectionwell.js
365-
msgid "remove all"
373+
msgid "Cancel selection"
366374
msgstr ""
367375

368376
#: ./src/pat/structure/js/views/table.js
@@ -385,6 +393,10 @@ msgstr ""
385393
msgid "Drag and drop reordering is disabled while filters are applied."
386394
msgstr ""
387395

396+
#: ./src/pat/structure/js/views/textfilter.js
397+
msgid "Filter"
398+
msgstr ""
399+
388400
#: ./src/pat/structure/templates/actionmenu.xml
389401
msgid "Actions"
390402
msgstr ""
@@ -409,10 +421,6 @@ msgstr ""
409421
msgid "Root"
410422
msgstr ""
411423

412-
#: ./src/pat/structure/templates/table.xml
413-
msgid "Select all"
414-
msgstr ""
415-
416424
#: ./src/pat/structure/templates/tablerow.xml
417425
msgid "Excluded from navigation"
418426
msgstr ""

0 commit comments

Comments
 (0)