mirror of
https://github.com/wekan/wekan.git
synced 2026-02-25 17:34:07 +01:00
Implement multi-selection
The UI and the internal APIs are still rough around the edges but the feature is basically working. You can now select multiple cards and move them together or (un|)assign them a label.
This commit is contained in:
parent
6457615e6a
commit
2c0030da62
45 changed files with 883 additions and 933 deletions
|
|
@ -8,7 +8,10 @@ template(name="board")
|
|||
template(name="boardComponent")
|
||||
if this
|
||||
.board-wrapper(class=colorClass)
|
||||
.board-canvas(class=sidebarSize)
|
||||
.board-canvas(
|
||||
class=sidebarSize
|
||||
class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}"
|
||||
class="{{#if draggingActive.get}}is-dragging-active{{/if}}")
|
||||
.lists.js-lists
|
||||
each lists
|
||||
+list(this)
|
||||
|
|
|
|||
|
|
@ -12,14 +12,16 @@ BlazeComponent.extendComponent({
|
|||
return 'boardComponent';
|
||||
},
|
||||
|
||||
onCreated: function() {
|
||||
this.draggingActive = new ReactiveVar(false);
|
||||
},
|
||||
|
||||
openNewListForm: function() {
|
||||
this.componentChildren('addListForm')[0].open();
|
||||
},
|
||||
|
||||
showNewCardForms: function(value) {
|
||||
_.each(this.componentChildren('list'), function(listComponent) {
|
||||
listComponent.showNewCardForm(value);
|
||||
});
|
||||
setIsDragging: function(bool) {
|
||||
this.draggingActive.set(bool);
|
||||
},
|
||||
|
||||
scrollLeft: function(position) {
|
||||
|
|
@ -79,8 +81,8 @@ BlazeComponent.extendComponent({
|
|||
helper: 'clone',
|
||||
items: '.js-list:not(.js-list-composer)',
|
||||
placeholder: 'list placeholder',
|
||||
start: function(event, ui) {
|
||||
$('.list.placeholder').height(ui.item.height());
|
||||
start: function(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
Popup.close();
|
||||
},
|
||||
stop: function() {
|
||||
|
|
@ -97,6 +99,11 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
});
|
||||
|
||||
// Disable drag-dropping while in multi-selection mode
|
||||
self.autorun(function() {
|
||||
self.$(lists).sortable('option', 'disabled', MultiSelection.isActive());
|
||||
});
|
||||
|
||||
// If there is no data in the board (ie, no lists) we autofocus the list
|
||||
// creation form by clicking on the corresponding element.
|
||||
if (self.data().lists().count() === 0) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@
|
|||
&.next-sidebar
|
||||
margin-right: 248px
|
||||
|
||||
&.is-dragging-active
|
||||
|
||||
.open-minicard-composer
|
||||
display: none
|
||||
|
||||
.lists
|
||||
align-items: flex-start
|
||||
display: flex
|
||||
|
|
|
|||
|
|
@ -27,15 +27,43 @@ template(name="headerBoard")
|
|||
i.fa.fa-times-thin
|
||||
else
|
||||
span {{_ 'filter'}}
|
||||
|
||||
if currentUser.isBoardMember
|
||||
a.board-header-btn.js-multiselection-activate(
|
||||
title="{{#if MultiSelection.isActive}}{{_ 'filter-on-desc'}}{{/if}}"
|
||||
class="{{#if MultiSelection.isActive}}emphasis{{/if}}")
|
||||
i.fa.fa-check-square-o
|
||||
if MultiSelection.isActive
|
||||
span Multi-Selection is on
|
||||
a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}")
|
||||
i.fa.fa-times-thin
|
||||
else
|
||||
span Multi-Selection
|
||||
|
||||
.separator
|
||||
a.board-header-btn.js-open-board-menu
|
||||
i.board-header-btn-icon.fa.fa-cog
|
||||
|
||||
template(name="boardMenuPopup")
|
||||
if currentUser.isBoardMember
|
||||
ul.pop-over-list
|
||||
li: a Archived elements
|
||||
li: a.js-change-board-color Change color
|
||||
li: a Permissions
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-change-board-color Change color
|
||||
li: a Copy this board
|
||||
li: a Permissions
|
||||
//-
|
||||
XXX Language should be handled by sandstorm, but for now display a
|
||||
language selection link in the board menu. This link is normally present
|
||||
in the header bar that is not displayed on sandstorm.
|
||||
if isSandstorm
|
||||
li: a.js-change-language {{_ 'language'}}
|
||||
unless isSandstorm
|
||||
if currentUser.isBoardAdmin
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a Close Board…
|
||||
|
||||
template(name="boardVisibilityList")
|
||||
ul.pop-over-list
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
Template.boardMenuPopup.events({
|
||||
'click .js-rename-board': Popup.open('boardChangeTitle'),
|
||||
'click .js-change-board-color': Popup.open('boardChangeColor')
|
||||
'click .js-change-board-color': Popup.open('boardChangeColor'),
|
||||
'click .js-change-language': Popup.open('setLanguage')
|
||||
});
|
||||
|
||||
Template.boardChangeTitlePopup.events({
|
||||
|
|
@ -24,14 +25,15 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
|
||||
isStarred: function() {
|
||||
var boardId = this.currentData()._id;
|
||||
var currentBoard = this.currentData();
|
||||
var user = Meteor.user();
|
||||
return boardId && user && user.hasStarred(boardId);
|
||||
return currentBoard && user && user.hasStarred(currentBoard._id);
|
||||
},
|
||||
|
||||
// Only show the star counter if the number of star is greater than 2
|
||||
showStarCounter: function() {
|
||||
return this.currentData().stars > 2;
|
||||
var currentBoard = this.currentData();
|
||||
return currentBoard && currentBoard.stars > 2;
|
||||
},
|
||||
|
||||
events: function() {
|
||||
|
|
@ -49,6 +51,17 @@ BlazeComponent.extendComponent({
|
|||
evt.stopPropagation();
|
||||
Sidebar.setView();
|
||||
Filter.reset();
|
||||
},
|
||||
'click .js-multiselection-activate': function() {
|
||||
var currentCard = Session.get('currentCard');
|
||||
MultiSelection.activate();
|
||||
if (currentCard) {
|
||||
MultiSelection.add(currentCard);
|
||||
}
|
||||
},
|
||||
'click .js-multiselection-reset': function(evt) {
|
||||
evt.stopPropagation();
|
||||
MultiSelection.disable();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
// We define a set of six board colors that we took from the FlatUI palette.
|
||||
// http://flatuicolors.com
|
||||
|
||||
//
|
||||
// XXX Centralizing all these properties in a single file just because their
|
||||
// value is derivedform the same color, doesn't make any sense. We should create
|
||||
// a macro that would generate 6 version of a given propertie and dispatch this
|
||||
// list in the other stylus files.
|
||||
setBoardColor(color)
|
||||
&#header,
|
||||
&.sk-spinner div,
|
||||
|
|
@ -8,13 +12,16 @@ setBoardColor(color)
|
|||
.board-list & a
|
||||
background-color: color
|
||||
|
||||
& .minicard.is-selected .minicard-details
|
||||
.is-selected .minicard
|
||||
border-left: 3px solid color
|
||||
|
||||
&.pop-over .pop-over-list li a:hover,
|
||||
button[type=submit].primary, input[type=submit].primary
|
||||
background-color: darken(color, 20%)
|
||||
|
||||
&.pop-over .pop-over-list li a:hover,
|
||||
.sidebar-list li a:hover
|
||||
background-color: lighten(color, 10%)
|
||||
|
||||
&#header #header-quick-access ul li.current
|
||||
border-bottom: 2px solid lighten(color, 10%)
|
||||
|
||||
|
|
@ -28,6 +35,17 @@ setBoardColor(color)
|
|||
&:hover .board-header-btn-close
|
||||
background: darken(complement(color), 20%)
|
||||
|
||||
.materialCheckBox.is-checked
|
||||
border-bottom: 2px solid color
|
||||
border-right: 2px solid color
|
||||
|
||||
.is-multiselection-active .multi-selection-checkbox
|
||||
&.is-checked + .minicard
|
||||
background: lighten(color, 90%)
|
||||
|
||||
&:not(.is-checked) + .minicard:hover:not(.minicard-composer)
|
||||
background: lighten(color, 97%)
|
||||
|
||||
.board-color-nephritis
|
||||
setBoardColor(#27AE60)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ Router.route('/boards/:_id/:slug', {
|
|||
onAfterAction: function() {
|
||||
// XXX We probably shouldn't rely on Session
|
||||
Session.set('sidebarIsOpen', true);
|
||||
Session.set('currentWidget', 'home');
|
||||
Session.set('menuWidgetIsOpen', false);
|
||||
},
|
||||
waitOn: function() {
|
||||
|
|
@ -37,6 +36,7 @@ Router.route('/boards/:_id/:slug', {
|
|||
Router.route('/boards/:boardId/:slug/:cardId', {
|
||||
name: 'Card',
|
||||
template: 'board',
|
||||
noEscapeActions: true,
|
||||
onAfterAction: function() {
|
||||
Tracker.nonreactive(function() {
|
||||
if (! Session.get('currentCard') && Sidebar) {
|
||||
|
|
@ -57,7 +57,7 @@ Router.route('/boards/:boardId/:slug/:cardId', {
|
|||
});
|
||||
|
||||
// Close the card details pane by pressing escape
|
||||
EscapeActions.register('detailedPane',
|
||||
function() { return ! Session.equals('currentCard', null); },
|
||||
function() { Utils.goBoardId(Session.get('currentBoard')); }
|
||||
EscapeActions.register('detailsPane',
|
||||
function() { Utils.goBoardId(Session.get('currentBoard')); },
|
||||
function() { return ! Session.equals('currentCard', null); }
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue