mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 15:30:13 +01:00
Improve the multi-selection experience
New features: - select all filtered cards - assign or unassign a member to selected cards - archive selected cards This commit also fix the card sort indexes calculation when a multi- selection is drag-dropped.
This commit is contained in:
parent
a41e07b37e
commit
5478fc93db
12 changed files with 146 additions and 53 deletions
|
|
@ -51,6 +51,19 @@
|
|||
.fa.fa-check
|
||||
margin: 0 4px
|
||||
|
||||
.sidebar-btn
|
||||
display: block
|
||||
margin: 5px 0
|
||||
padding: 10px
|
||||
border-radius: 3px
|
||||
background: darken(white, 10%)
|
||||
|
||||
&:hover *
|
||||
color: white
|
||||
|
||||
i.fa
|
||||
margin-right: 10px
|
||||
|
||||
.board-sidebar
|
||||
width: 248px
|
||||
right: -@width
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//-
|
||||
XXX There is a *lot* of code duplication in the above templates and in the
|
||||
XXX There is a *lot* of code duplication in the below templates and in the
|
||||
corresponding JavaScript components. We will probably need the upcoming #let
|
||||
and #each x in y constructors.
|
||||
and #each x in y constructors to fix this.
|
||||
|
||||
template(name="filterSidebar")
|
||||
ul.sidebar-list
|
||||
|
|
@ -16,22 +16,27 @@ template(name="filterSidebar")
|
|||
span.quiet {{_ "label-default" color}}
|
||||
if Filter.labelIds.isSelected _id
|
||||
i.fa.fa-check
|
||||
hr
|
||||
ul.sidebar-list
|
||||
each currentBoard.members
|
||||
if isActive
|
||||
with getUser userId
|
||||
li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
|
||||
a.name.js-toogle-member-filter
|
||||
+userAvatar(userId=this._id)
|
||||
span.sidebar-list-item-description
|
||||
= profile.name
|
||||
| (<span class="username">{{ username }}</span>)
|
||||
if Filter.members.isSelected _id
|
||||
i.fa.fa-check
|
||||
if Filter.isActive
|
||||
hr
|
||||
ul.sidebar-list
|
||||
each currentBoard.members
|
||||
if isActive
|
||||
with getUser userId
|
||||
li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
|
||||
a.name.js-toogle-member-filter
|
||||
+userAvatar(userId=this._id)
|
||||
span.sidebar-list-item-description
|
||||
= profile.name
|
||||
| (<span class="username">{{ username }}</span>)
|
||||
if Filter.members.isSelected _id
|
||||
i.fa.fa-check
|
||||
hr
|
||||
a.js-clear-all(class="{{#unless Filter.isActive}}disabled{{/unless}}")
|
||||
| {{_ 'filter-clear'}}
|
||||
a.sidebar-btn.js-clear-all
|
||||
i.fa.fa-filter
|
||||
span {{_ 'filter-clear'}}
|
||||
a.sidebar-btn.js-filter-to-selection
|
||||
i.fa.fa-check-square-o
|
||||
span Filter to selection
|
||||
|
||||
template(name="multiselectionSidebar")
|
||||
ul.sidebar-list
|
||||
|
|
@ -48,10 +53,32 @@ template(name="multiselectionSidebar")
|
|||
i.fa.fa-check
|
||||
else if someSelectedElementHave 'label' _id
|
||||
i.fa.fa-ellipsis-h
|
||||
//-
|
||||
XXX We should be able to assign a member to the list of selected cards.
|
||||
hr
|
||||
ul.sidebar-list
|
||||
each currentBoard.members
|
||||
if isActive
|
||||
with getUser userId
|
||||
li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
|
||||
a.name.js-toogle-member-multiselection
|
||||
+userAvatar(userId=this._id)
|
||||
span.sidebar-list-item-description
|
||||
= profile.name
|
||||
| (<span class="username">{{ username }}</span>)
|
||||
if allSelectedElementHave 'member' _id
|
||||
i.fa.fa-check
|
||||
else if someSelectedElementHave 'member' _id
|
||||
i.fa.fa-ellipsis-h
|
||||
hr
|
||||
a.sidebar-btn.js-archive-selection
|
||||
i.fa.fa-archive
|
||||
span Archive selection
|
||||
|
||||
template(name="disambiguateMultiLabelPopup")
|
||||
p What do you want to do?
|
||||
button.wide.js-remove-label Remove the label
|
||||
button.wide.js-add-label Add the label
|
||||
|
||||
template(name="disambiguateMultiMemberPopup")
|
||||
p What do you want to do?
|
||||
button.wide.js-unassign-member Unassign member
|
||||
button.wide.js-assign-member Assign member
|
||||
|
|
|
|||
|
|
@ -5,19 +5,26 @@ BlazeComponent.extendComponent({
|
|||
|
||||
events: function() {
|
||||
return [{
|
||||
'click .js-toggle-label-filter': function(event) {
|
||||
'click .js-toggle-label-filter': function(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.labelIds.toogle(this.currentData()._id);
|
||||
Filter.resetExceptions();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-toogle-member-filter': function(event) {
|
||||
'click .js-toogle-member-filter': function(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.members.toogle(this.currentData()._id);
|
||||
Filter.resetExceptions();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-clear-all': function(event) {
|
||||
'click .js-clear-all': function(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.reset();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-filter-to-selection': function(evt) {
|
||||
evt.preventDefault();
|
||||
var selectedCards = Cards.find(Filter.mongoSelector()).map(function(c) {
|
||||
return c._id;
|
||||
});
|
||||
MultiSelection.add(selectedCards);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
|
@ -57,7 +64,7 @@ BlazeComponent.extendComponent({
|
|||
|
||||
events: function() {
|
||||
return [{
|
||||
'click .js-toggle-label-multiselection': function(evt, tpl) {
|
||||
'click .js-toggle-label-multiselection': function(evt) {
|
||||
var labelId = this.currentData()._id;
|
||||
var mappedSelection = this.mapSelection('label', labelId);
|
||||
var operation;
|
||||
|
|
@ -69,7 +76,7 @@ BlazeComponent.extendComponent({
|
|||
var popup = Popup.open('disambiguateMultiLabel');
|
||||
// XXX We need to have a better integration between the popup and the
|
||||
// UI components systems.
|
||||
return popup.call(this.currentData(), evt, tpl);
|
||||
return popup.call(this.currentData(), evt);
|
||||
}
|
||||
|
||||
var query = {};
|
||||
|
|
@ -77,6 +84,30 @@ BlazeComponent.extendComponent({
|
|||
labelIds: labelId
|
||||
};
|
||||
updateSelectedCards(query);
|
||||
},
|
||||
'click .js-toogle-member-multiselection': function(evt) {
|
||||
var memberId = this.currentData()._id;
|
||||
var mappedSelection = this.mapSelection('member', memberId);
|
||||
var operation;
|
||||
if (_.every(mappedSelection))
|
||||
operation = '$pull';
|
||||
else if (_.every(mappedSelection, function(bool) { return ! bool; }))
|
||||
operation = '$addToSet';
|
||||
else {
|
||||
var popup = Popup.open('disambiguateMultiMember');
|
||||
// XXX We need to have a better integration between the popup and the
|
||||
// UI components systems.
|
||||
return popup.call(this.currentData(), evt);
|
||||
}
|
||||
|
||||
var query = {};
|
||||
query[operation] = {
|
||||
members: memberId
|
||||
};
|
||||
updateSelectedCards(query);
|
||||
},
|
||||
'click .js-archive-selection': function() {
|
||||
updateSelectedCards({$set: {archived: true}});
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
|
@ -92,3 +123,14 @@ Template.disambiguateMultiLabelPopup.events({
|
|||
Popup.close();
|
||||
}
|
||||
});
|
||||
|
||||
Template.disambiguateMultiMemberPopup.events({
|
||||
'click .js-unassign-member': function() {
|
||||
updateSelectedCards({$pull: {members: this._id}});
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-assign-member': function() {
|
||||
updateSelectedCards({$addToSet: {members: this._id}});
|
||||
Popup.close();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue