mirror of
https://github.com/wekan/wekan.git
synced 2025-12-18 00:10:13 +01:00
feature implemented, known bugs fixed
This commit is contained in:
parent
c865bfe497
commit
214fe6a61f
6 changed files with 71 additions and 45 deletions
|
|
@ -81,7 +81,7 @@ BlazeComponent.extendComponent({
|
||||||
function userIsMember() {
|
function userIsMember() {
|
||||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable drag-dropping if the current user is not a board member or is comment only
|
// Disable drag-dropping if the current user is not a board member or is comment only
|
||||||
this.autorun(() => {
|
this.autorun(() => {
|
||||||
$cards.sortable('option', 'disabled', !userIsMember());
|
$cards.sortable('option', 'disabled', !userIsMember());
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,8 @@ BlazeComponent.extendComponent({
|
||||||
|
|
||||||
reachedWipLimit() {
|
reachedWipLimit() {
|
||||||
const list = Template.currentData();
|
const list = Template.currentData();
|
||||||
return list.wipLimit.enabled && list.wipLimit.value == list.cards().count();
|
if( !list.getWipLimit() ) { return false; }
|
||||||
|
return list.getWipLimit('enabled') && list.getWipLimit('value') === list.cards().count();
|
||||||
},
|
},
|
||||||
|
|
||||||
events() {
|
events() {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ template(name="listHeader")
|
||||||
= title
|
= title
|
||||||
if isWipLimitEnabled
|
if isWipLimitEnabled
|
||||||
span
|
span
|
||||||
| (#{wipLimit.value})
|
| ({{cards.count}}/#{wipLimit.value})
|
||||||
if showCardsCountForList cards.count
|
if showCardsCountForList cards.count
|
||||||
= cards.count
|
= cards.count
|
||||||
span.lowercase
|
span.lowercase
|
||||||
|
|
@ -77,11 +77,11 @@ template(name="setWipLimitPopup")
|
||||||
lable {{_ 'set-wip-limit-value'}}
|
lable {{_ 'set-wip-limit-value'}}
|
||||||
ul.pop-over-list
|
ul.pop-over-list
|
||||||
li: a.js-enable-wip-limit Enable WIP Limit
|
li: a.js-enable-wip-limit Enable WIP Limit
|
||||||
if wipEnabled.get
|
if isWipLimitEnabled
|
||||||
i.fa.fa-check
|
i.fa.fa-check
|
||||||
if wipEnabled.get
|
if isWipLimitEnabled
|
||||||
p
|
p
|
||||||
input.wip-limit-value(type="number" value="#{wipLimit.value}" min="1" max="99" onkeydown="return false")
|
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-apply(type="submit" value="{{_ 'apply'}}")
|
||||||
input.wip-limit-error
|
input.wip-limit-error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,19 @@ BlazeComponent.extendComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
isWipLimitEnabled() {
|
|
||||||
const limit = this.currentData().wipLimit
|
|
||||||
return limit.enabled && limit.value > 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
isWatching() {
|
isWatching() {
|
||||||
const list = this.currentData();
|
const list = this.currentData();
|
||||||
return list.findWatcher(Meteor.userId());
|
return list.findWatcher(Meteor.userId());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isWipLimitEnabled() {
|
||||||
|
const wipLimit = this.currentData().getWipLimit();
|
||||||
|
if(!wipLimit) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return wipLimit.enabled && wipLimit.value > 0;
|
||||||
|
},
|
||||||
|
|
||||||
limitToShowCardsCount() {
|
limitToShowCardsCount() {
|
||||||
return Meteor.user().getLimitToShowCardsCount();
|
return Meteor.user().getLimitToShowCardsCount();
|
||||||
},
|
},
|
||||||
|
|
@ -43,12 +46,7 @@ BlazeComponent.extendComponent({
|
||||||
|
|
||||||
Template.listActionPopup.helpers({
|
Template.listActionPopup.helpers({
|
||||||
isWipLimitEnabled() {
|
isWipLimitEnabled() {
|
||||||
const prevState = Template.parentData(4).stack[0].dataContext.wipEnableState;
|
return Template.currentData().getWipLimit('enabled');
|
||||||
// If user was already inside setWipLimitPopup, return previous state. Popup stack not reacting to database mutations
|
|
||||||
if(typeof prevState !== "undefined") {
|
|
||||||
return prevState;
|
|
||||||
}
|
|
||||||
return Template.currentData().wipLimit.enabled;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isWatching() {
|
isWatching() {
|
||||||
|
|
@ -80,43 +78,33 @@ Template.listActionPopup.events({
|
||||||
});
|
});
|
||||||
|
|
||||||
BlazeComponent.extendComponent({
|
BlazeComponent.extendComponent({
|
||||||
onCreated() {
|
|
||||||
const prevState = Template.parentData(4).stack[0].dataContext.wipEnableState;
|
|
||||||
// Check if the user as already opened this popup before and retrieve previous state
|
|
||||||
// This check is necessary due to the fact that database mutations inside popups are not reactive inside the popup stack.
|
|
||||||
//The use of ReactiveVar is due to the same reason.
|
|
||||||
if(typeof prevState !== "undefined") {
|
|
||||||
this.wipEnabled = new ReactiveVar(prevState)
|
|
||||||
} else {
|
|
||||||
this.wipEnabled = new ReactiveVar(Template.currentData().wipLimit.enabled);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onDestroyed() {
|
|
||||||
// Save current wipEnabled state in the first element of the popup stack to maintain UI coherence if user returns to popup
|
|
||||||
Template.parentData(4).stack[0].dataContext.wipEnableState = this.wipEnabled.get();
|
|
||||||
},
|
|
||||||
|
|
||||||
applyWipLimit() {
|
applyWipLimit() {
|
||||||
const list = Template.currentData();
|
const list = Template.currentData();
|
||||||
const limit = Template.instance().$('.wip-limit-value').val();
|
const limit = parseInt(Template.instance().$('.wip-limit-value').val(), 10);
|
||||||
|
|
||||||
if(limit < list.cards().count()){
|
if(limit < list.cards().count()){
|
||||||
Template.instance().$('.wip-limit-error').click();
|
Template.instance().$('.wip-limit-error').click();
|
||||||
} else {
|
} else {
|
||||||
list.setWipLimit(limit);
|
Meteor.call('applyWipLimit', list._id, limit);
|
||||||
|
Popup.back();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
enableWipLimit() {
|
enableWipLimit() {
|
||||||
const list = Template.currentData();
|
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
|
// Prevent user from using previously stored wipLimit.value if it is less than the current number of cards in the list
|
||||||
if(!list.wipLimit.enabled && list.wipLimit.value < list.cards().count()){
|
if(list.getWipLimit() && !list.wipLimit.enabled && list.wipLimit.value < list.cards().count()){
|
||||||
list.setWipLimit(list.cards().count());
|
list.setWipLimit(list.cards().count());
|
||||||
}
|
}
|
||||||
|
Meteor.call('enableWipLimit', Template.currentData()._id);
|
||||||
|
},
|
||||||
|
|
||||||
this.wipEnabled.set(!this.wipEnabled.get()); //If wipLimit.enabled is not yet definied, the negation of "undefined" is "true"
|
isWipLimitEnabled() {
|
||||||
list.toggleWipLimit(this.wipEnabled.get());
|
return Template.currentData().getWipLimit('enabled');
|
||||||
|
},
|
||||||
|
|
||||||
|
wipLimitValue(){
|
||||||
|
return Template.currentData().getWipLimit('value');
|
||||||
},
|
},
|
||||||
|
|
||||||
events() {
|
events() {
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ Cards.helpers({
|
||||||
|
|
||||||
canBeRestored() {
|
canBeRestored() {
|
||||||
const list = Lists.findOne({_id: this.listId});
|
const list = Lists.findOne({_id: this.listId});
|
||||||
if(list.wipLimit.enabled && list.wipLimit.value == list.cards().count()){
|
if(list.getWipLimit() && list.getWipLimit('enabled') && list.getWipLimit('value') === list.cards().count()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -46,16 +46,24 @@ Lists.attachSchema(new SimpleSchema({
|
||||||
type: Object,
|
type: Object,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
"wipLimit.value": {
|
'wipLimit.value': {
|
||||||
type: SimpleSchema.Integer,
|
type: Number,
|
||||||
|
decimal: false,
|
||||||
|
autoValue() {
|
||||||
|
if(this.isInsert){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return this.value;
|
||||||
|
},
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
"wipLimit.enabled":{
|
'wipLimit.enabled':{
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
autoValue() {
|
autoValue() {
|
||||||
if(this.isInsert){
|
if(this.isInsert){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return this.value;
|
||||||
},
|
},
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
|
@ -89,6 +97,17 @@ Lists.helpers({
|
||||||
board() {
|
board() {
|
||||||
return Boards.findOne(this.boardId);
|
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({
|
Lists.mutations({
|
||||||
|
|
@ -105,11 +124,29 @@ Lists.mutations({
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleWipLimit(toggle) {
|
toggleWipLimit(toggle) {
|
||||||
return { $set: { "wipLimit.enabled": toggle } };
|
return { $set: { 'wipLimit.enabled': toggle } };
|
||||||
},
|
},
|
||||||
|
|
||||||
setWipLimit(limit) {
|
setWipLimit(limit) {
|
||||||
return { $set: { "wipLimit.value": 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.wipLimit.enabled);
|
||||||
|
} else {
|
||||||
|
list.toggleWipLimit(true); // First time toggle is always to 'true' because default is 'false'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue