Merge branch 'issue783' of https://github.com/amadilsons/wekan into amadilsons-issue783

This commit is contained in:
Lauri Ojansivu 2017-10-09 14:49:38 +03:00
commit fb060ed2c5
13 changed files with 202 additions and 13 deletions

View file

@ -22,7 +22,7 @@ BlazeComponent.extendComponent({
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
const $cards = this.$('.js-minicards');
$cards.sortable({
connectWith: '.js-minicards',
connectWith: '.js-minicards:not(.js-list-full)',
tolerance: 'pointer',
appendTo: 'body',
helper(evt, item) {

View file

@ -110,3 +110,19 @@
background: #fafafa
color: #222
box-shadow: 0 1px 2px rgba(0,0,0,.2)
#js-wip-limit-edit
padding-top: 2%
p
margin-bottom: 0
input
display: inline-block
.wip-limit-value
width: 20%
margin-right: 5%
.wip-limit-error
display: none

View file

@ -1,6 +1,6 @@
template(name="listBody")
.list-body.js-perfect-scrollbar
.minicards.clearfix.js-minicards
.minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}")
if cards.count
+inlinedForm(autoclose=false position="top")
+addCardForm(listId=_id position="top")

View file

@ -96,6 +96,16 @@ BlazeComponent.extendComponent({
MultiSelection.toggle(this.currentData()._id);
},
canSeeAddCard() {
return !this.reachedWipLimit() && Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
},
reachedWipLimit() {
const list = Template.currentData();
if( !list.getWipLimit() ) { return false; }
return list.getWipLimit('enabled') && list.getWipLimit('value') === list.cards().count();
},
events() {
return [{
'click .js-minicard': this.clickOnMiniCard,
@ -239,10 +249,3 @@ BlazeComponent.extendComponent({
});
},
}).register('addCardForm');
Template.listBody.helpers({
canSeeAddCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
},
});

View file

@ -6,6 +6,9 @@ template(name="listHeader")
h2.list-header-name(
class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}")
= title
if isWipLimitEnabled
span
| ({{cards.count}}/#{wipLimit.value})
if showCardsCountForList cards.count
= cards.count
span.lowercase
@ -33,6 +36,10 @@ template(name="listActionPopup")
if cards.count
li: a.js-select-cards {{_ 'list-select-cards'}}
hr
if currentUser.isBoardAdmin
ul.pop-over-list
li: a.js-set-wip-limit {{#if isWipLimitEnabled }}{{_ 'edit-wip-limit'}}{{else}}{{_ 'setWipLimitPopup-title'}}{{/if}}
hr
ul.pop-over-list
li: a.js-close-list {{_ 'archive-list'}}
hr
@ -64,3 +71,22 @@ template(name="listDeletePopup")
unless archived
p {{_ "list-delete-suggest-archive"}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="setWipLimitPopup")
#js-wip-limit-edit
lable {{_ 'set-wip-limit-value'}}
ul.pop-over-list
li: a.js-enable-wip-limit {{_ 'enable-wip-limit'}}
if isWipLimitEnabled
i.fa.fa-check
if isWipLimitEnabled
p
input.wip-limit-value(type="number" value="{{ wipLimitValue }}" min="1" max="99" onkeydown="return false")
input.wip-limit-apply(type="submit" value="{{_ 'apply'}}")
input.wip-limit-error
template(name="wipLimitErrorPopup")
.wip-limit-invalid
p {{_ 'wipLimitErrorPopup-dialog-pt1'}}
p {{_ 'wipLimitErrorPopup-dialog-pt2'}}
button.full.js-back-view(type="submit") {{_ 'cancel'}}

View file

@ -13,6 +13,14 @@ BlazeComponent.extendComponent({
return list.findWatcher(Meteor.userId());
},
isWipLimitEnabled() {
const wipLimit = this.currentData().getWipLimit();
if(!wipLimit) {
return 0;
}
return wipLimit.enabled && wipLimit.value > 0;
},
limitToShowCardsCount() {
return Meteor.user().getLimitToShowCardsCount();
},
@ -37,6 +45,10 @@ BlazeComponent.extendComponent({
}).register('listHeader');
Template.listActionPopup.helpers({
isWipLimitEnabled() {
return Template.currentData().getWipLimit('enabled');
},
isWatching() {
return this.findWatcher(Meteor.userId());
},
@ -61,9 +73,49 @@ Template.listActionPopup.events({
this.archive();
Popup.close();
},
'click .js-set-wip-limit': Popup.open('setWipLimit'),
'click .js-more': Popup.open('listMore'),
});
BlazeComponent.extendComponent({
applyWipLimit() {
const list = Template.currentData();
const limit = parseInt(Template.instance().$('.wip-limit-value').val(), 10);
if(limit < list.cards().count()){
Template.instance().$('.wip-limit-error').click();
} else {
Meteor.call('applyWipLimit', list._id, limit);
Popup.back();
}
},
enableWipLimit() {
const list = Template.currentData();
// Prevent user from using previously stored wipLimit.value if it is less than the current number of cards in the list
if(list.getWipLimit() && !list.getWipLimit('enabled') && list.getWipLimit('value') < list.cards().count()){
list.setWipLimit(list.cards().count());
}
Meteor.call('enableWipLimit', list._id);
},
isWipLimitEnabled() {
return Template.currentData().getWipLimit('enabled');
},
wipLimitValue(){
return Template.currentData().getWipLimit('value');
},
events() {
return [{
'click .js-enable-wip-limit': this.enableWipLimit,
'click .wip-limit-apply': this.applyWipLimit,
'click .wip-limit-error': Popup.open('wipLimitError'),
}];
},
}).register('setWipLimitPopup');
Template.listMorePopup.events({
'click .js-delete': Popup.afterConfirm('listDelete', function () {
Popup.close();

View file

@ -32,7 +32,9 @@ BlazeComponent.extendComponent({
return [{
'click .js-restore-card'() {
const card = this.currentData();
card.restore();
if(card.canBeRestored()){
card.restore();
}
},
'click .js-delete-card': Popup.afterConfirm('cardDelete', function() {
const cardId = this._id;

View file

@ -205,4 +205,3 @@ escapeActions.forEach((actionName) => {
}
);
});

View file

@ -171,6 +171,7 @@
"edit": "Edit",
"edit-avatar": "Change Avatar",
"edit-profile": "Edit Profile",
"edit-wip-limit": "Edit WIP Limit",
"editCardStartDatePopup-title": "Change start date",
"editCardDueDatePopup-title": "Change due date",
"editLabelPopup-title": "Change Label",
@ -189,6 +190,7 @@
"email-sent": "Email sent",
"email-verifyEmail-subject": "Verify your email address on __siteName__",
"email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
"enable-wip-limit": "Enable WIP Limit",
"error-board-doesNotExist": "This board does not exist",
"error-board-notAdmin": "You need to be admin of this board to do that",
"error-board-notAMember": "You need to be a member of this board to do that",
@ -310,6 +312,8 @@
"save": "Save",
"search": "Search",
"select-color": "Select Color",
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list:",
"setWipLimitPopup-title": "Set WIP Limit",
"shortcut-assign-self": "Assign yourself to current card",
"shortcut-autocomplete-emoji": "Autocomplete emoji",
"shortcut-autocomplete-members": "Autocomplete members",
@ -350,6 +354,9 @@
"welcome-list1": "Basics",
"welcome-list2": "Advanced",
"what-to-do": "What do you want to do?",
"wipLimitErrorPopup-title": "Invalid WIP Limit",
"wipLimitErrorPopup-dialog-pt1": "The number of tasks in this list is higher than the WIP limit you've defined.",
"wipLimitErrorPopup-dialog-pt2": "Please move some tasks out of this list, or set a higher WIP limit.",
"admin-panel": "Admin Panel",
"settings": "Settings",
"people": "People",
@ -395,4 +402,4 @@
"no": "No",
"accounts": "Accounts",
"accounts-allowEmailChange": "Allow Email Change"
}
}

View file

@ -171,6 +171,7 @@
"edit": "Edit",
"edit-avatar": "Change Avatar",
"edit-profile": "Edit Profile",
"edit-wip-limit": "Edit WIP Limit",
"editCardStartDatePopup-title": "Change start date",
"editCardDueDatePopup-title": "Change due date",
"editLabelPopup-title": "Change Label",
@ -189,6 +190,7 @@
"email-sent": "Email sent",
"email-verifyEmail-subject": "Verify your email address on __siteName__",
"email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
"enable-wip-limit": "Enable WIP Limit",
"error-board-doesNotExist": "This board does not exist",
"error-board-notAdmin": "You need to be admin of this board to do that",
"error-board-notAMember": "You need to be a member of this board to do that",
@ -310,6 +312,8 @@
"save": "Save",
"search": "Search",
"select-color": "Select Color",
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
"setWipLimitPopup-title": "Set WIP Limit",
"shortcut-assign-self": "Assign yourself to current card",
"shortcut-autocomplete-emoji": "Autocomplete emoji",
"shortcut-autocomplete-members": "Autocomplete members",
@ -350,6 +354,9 @@
"welcome-list1": "Basics",
"welcome-list2": "Advanced",
"what-to-do": "What do you want to do?",
"wipLimitErrorPopup-title": "Invalid WIP Limit",
"wipLimitErrorPopup-dialog-pt1": "The number of tasks in this list is higher than the WIP limit you've defined.",
"wipLimitErrorPopup-dialog-pt2": "Please move some tasks out of this list, or set a higher WIP limit.",
"admin-panel": "Admin Panel",
"settings": "Settings",
"people": "People",

View file

@ -171,6 +171,7 @@
"edit": "Editar",
"edit-avatar": "Alterar Avatar",
"edit-profile": "Editar Perfil",
"edit-wip-limit": "Editar Limite WIP",
"editCardStartDatePopup-title": "Altera data de início",
"editCardDueDatePopup-title": "Altera data fim",
"editLabelPopup-title": "Alterar Etiqueta",
@ -189,6 +190,7 @@
"email-sent": "Email enviado",
"email-verifyEmail-subject": "Verifique seu endereço de email em __siteName__",
"email-verifyEmail-text": "Olá __user__\nPara verificar sua conta de email, clique no link abaixo.\n__url__\nObrigado.",
"enable-wip-limit": "Ativar Limite WIP",
"error-board-doesNotExist": "Este quadro não existe",
"error-board-notAdmin": "Você precisa ser administrador desse quadro para fazer isto",
"error-board-notAMember": "Você precisa ser um membro desse quadro para fazer isto",
@ -310,6 +312,8 @@
"save": "Salvar",
"search": "Buscar",
"select-color": "Selecionar Cor",
"set-wip-limit-value": "Defina um limite máximo para o número de tarefas nesta lista",
"setWipLimitPopup-title": "Definir Limite WIP",
"shortcut-assign-self": "Atribuir a si o cartão atual",
"shortcut-autocomplete-emoji": "Autocompletar emoji",
"shortcut-autocomplete-members": "Preenchimento automático de membros",
@ -350,6 +354,9 @@
"welcome-list1": "Básico",
"welcome-list2": "Avançado",
"what-to-do": "O que você gostaria de fazer?",
"wipLimitErrorPopup-title": "Limite WIP Inválido",
"wipLimitErrorPopup-dialog-pt1": "O número de tarefas nesta lista excede o limite WIP definido.",
"wipLimitErrorPopup-dialog-pt2": "Por favor, mova algumas tarefas para fora desta lista, ou defina um limite WIP mais elevado.",
"admin-panel": "Painel Administrativo",
"settings": "Configurações",
"people": "Pessoas",
@ -395,4 +402,4 @@
"no": "Não",
"accounts": "Contas",
"accounts-allowEmailChange": "Permitir Mudança de Email"
}
}

View file

@ -179,6 +179,14 @@ Cards.helpers({
cardId: this._id,
});
},
canBeRestored() {
const list = Lists.findOne({_id: this.listId});
if(list.getWipLimit() && list.getWipLimit('enabled') && list.getWipLimit('value') === list.cards().count()){
return false;
}
return true;
},
});
Cards.mutations({

View file

@ -42,6 +42,31 @@ Lists.attachSchema(new SimpleSchema({
}
},
},
wipLimit: {
type: Object,
optional: true,
},
'wipLimit.value': {
type: Number,
decimal: false,
autoValue() {
if(this.isInsert){
return 0;
}
return this.value;
},
optional: true,
},
'wipLimit.enabled':{
type: Boolean,
autoValue() {
if(this.isInsert){
return false;
}
return this.value;
},
optional: true,
},
}));
Lists.allow({
@ -72,6 +97,17 @@ Lists.helpers({
board() {
return Boards.findOne(this.boardId);
},
getWipLimit(option){
const list = Lists.findOne({ _id: this._id });
if(!list.wipLimit) { // Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set
return 0;
} else if(!option) {
return list.wipLimit;
} else {
return list.wipLimit[option] ? list.wipLimit[option] : 0; // Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set
}
},
});
Lists.mutations({
@ -86,6 +122,32 @@ Lists.mutations({
restore() {
return { $set: { archived: false } };
},
toggleWipLimit(toggle) {
return { $set: { 'wipLimit.enabled': toggle } };
},
setWipLimit(limit) {
return { $set: { 'wipLimit.value': limit } };
},
});
Meteor.methods({
applyWipLimit(listId, limit){
check(listId, String);
check(limit, Number);
Lists.findOne({ _id: listId }).setWipLimit(limit);
},
enableWipLimit(listId) {
check(listId, String);
const list = Lists.findOne({ _id: listId });
if(list.getWipLimit()){ // Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set
list.toggleWipLimit(!list.getWipLimit('enabled'));
} else {
list.toggleWipLimit(true); // First time toggle is always to 'true' because default is 'false'
}
},
});
Lists.hookOptions.after.update = { fetchPrevious: false };