mirror of
https://github.com/wekan/wekan.git
synced 2026-02-27 10:24:07 +01:00
Merge branch 'frmwrk123-issue-876' into devel
Reorder checklists. Move checklist item to another checklist. Thanks to frmwrk123 ! Related #876
This commit is contained in:
commit
68897a77dc
4 changed files with 126 additions and 13 deletions
|
|
@ -1,3 +1,11 @@
|
||||||
|
# Upcoming Wekan release
|
||||||
|
|
||||||
|
This release adds the following new features:
|
||||||
|
|
||||||
|
* [Reorder checklists. Move checklist item to another checklist.](https://github.com/wekan/wekan/pull/1215)
|
||||||
|
|
||||||
|
Thanks to GitHub user frmwrk123 for contributions.
|
||||||
|
|
||||||
# v0.37 2017-09-09 Wekan release
|
# v0.37 2017-09-09 Wekan release
|
||||||
|
|
||||||
This release adds the following new features:
|
This release adds the following new features:
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ template(name="editChecklistItemForm")
|
||||||
a.js-delete-checklist-item {{_ "delete"}}...
|
a.js-delete-checklist-item {{_ "delete"}}...
|
||||||
|
|
||||||
template(name="checklistItems")
|
template(name="checklistItems")
|
||||||
.checklist-items
|
.checklist-items.js-checklist-items
|
||||||
each item in checklist.items
|
each item in checklist.getItems
|
||||||
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
|
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
|
||||||
+editChecklistItemForm(type = 'item' item = item checklist = checklist)
|
+editChecklistItemForm(type = 'item' item = item checklist = checklist)
|
||||||
else
|
else
|
||||||
|
|
@ -61,11 +61,10 @@ template(name="checklistItems")
|
||||||
| {{_ 'add-checklist-item'}}...
|
| {{_ 'add-checklist-item'}}...
|
||||||
|
|
||||||
template(name='itemDetail')
|
template(name='itemDetail')
|
||||||
.item
|
.item.js-checklist-item
|
||||||
if canModifyCard
|
if canModifyCard
|
||||||
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||||
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}") {{item.title}}
|
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}") {{item.title}}
|
||||||
else
|
else
|
||||||
.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||||
.item-title(class="{{#if item.isFinished }}is-checked{{/if}}") {{item.title}}
|
.item-title(class="{{#if item.isFinished }}is-checked{{/if}}") {{item.title}}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,81 @@
|
||||||
|
function initSorting(items) {
|
||||||
|
items.sortable({
|
||||||
|
tolerance: 'pointer',
|
||||||
|
helper: 'clone',
|
||||||
|
items: '.js-checklist-item:not(.placeholder)',
|
||||||
|
axis: 'y',
|
||||||
|
distance: 7,
|
||||||
|
placeholder: 'placeholder',
|
||||||
|
scroll: false,
|
||||||
|
start(evt, ui) {
|
||||||
|
ui.placeholder.height(ui.helper.height());
|
||||||
|
EscapeActions.executeUpTo('popup-close');
|
||||||
|
},
|
||||||
|
stop(evt, ui) {
|
||||||
|
const parent = ui.item.parents('.js-checklist-items');
|
||||||
|
const orderedItems = [];
|
||||||
|
parent.find('.js-checklist-item').each(function(i, item) {
|
||||||
|
const checklistItem = Blaze.getData(item).item;
|
||||||
|
orderedItems.push(checklistItem._id);
|
||||||
|
});
|
||||||
|
items.sortable('cancel');
|
||||||
|
const formerParent = ui.item.parents('.js-checklist-items');
|
||||||
|
let checklist = Blaze.getData(parent.get(0)).checklist;
|
||||||
|
const oldChecklist = Blaze.getData(formerParent.get(0)).checklist;
|
||||||
|
if (oldChecklist._id !== checklist._id) {
|
||||||
|
const currentItem = Blaze.getData(ui.item.get(0)).item;
|
||||||
|
for (let i = 0; i < orderedItems.length; i++) {
|
||||||
|
let itemId = orderedItems[i];
|
||||||
|
if (itemId !== currentItem._id) continue;
|
||||||
|
checklist.addItem(currentItem.title);
|
||||||
|
checklist = Checklists.findOne({_id: checklist._id});
|
||||||
|
itemId = checklist._id + (checklist.newItemIndex - 1);
|
||||||
|
if (currentItem.finished) {
|
||||||
|
checklist.finishItem(itemId);
|
||||||
|
}
|
||||||
|
orderedItems[i] = itemId;
|
||||||
|
oldChecklist.removeItem(currentItem._id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checklist.sortItems(orderedItems);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Template.checklists.onRendered(function () {
|
||||||
|
const self = BlazeComponent.getComponentForElement(this.firstNode);
|
||||||
|
self.itemsDom = this.$('.card-checklist-items');
|
||||||
|
initSorting(self.itemsDom);
|
||||||
|
self.itemsDom.mousedown(function(evt) {
|
||||||
|
evt.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
function userIsMember() {
|
||||||
|
return Meteor.user() && Meteor.user().isBoardMember();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable sorting if the current user is not a board member
|
||||||
|
self.autorun(() => {
|
||||||
|
const $itemsDom = $(self.itemsDom);
|
||||||
|
if ($itemsDom.data('sortable')) {
|
||||||
|
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
BlazeComponent.extendComponent({
|
BlazeComponent.extendComponent({
|
||||||
addChecklist(event) {
|
addChecklist(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const textarea = this.find('textarea.js-add-checklist-item');
|
const textarea = this.find('textarea.js-add-checklist-item');
|
||||||
const title = textarea.value.trim();
|
const title = textarea.value.trim();
|
||||||
const cardId = this.currentData().cardId;
|
const cardId = this.currentData().cardId;
|
||||||
|
const card = Cards.findOne(cardId);
|
||||||
|
|
||||||
if (title) {
|
if (title) {
|
||||||
Checklists.insert({
|
Checklists.insert({
|
||||||
cardId,
|
cardId,
|
||||||
title,
|
title,
|
||||||
|
sort: card.checklists().count(),
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$('.add-checklist-item').last().click();
|
this.$('.add-checklist-item').last().click();
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@ Checklists.attachSchema(new SimpleSchema({
|
||||||
'items.$.title': {
|
'items.$.title': {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
'items.$.sort': {
|
||||||
|
type: Number,
|
||||||
|
decimal: true,
|
||||||
|
},
|
||||||
'items.$.isFinished': {
|
'items.$.isFinished': {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
|
|
@ -36,12 +40,34 @@ Checklists.attachSchema(new SimpleSchema({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
sort: {
|
||||||
|
type: Number,
|
||||||
|
decimal: true,
|
||||||
|
},
|
||||||
|
newItemIndex: {
|
||||||
|
type: Number,
|
||||||
|
decimal: true,
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const self = Checklists;
|
||||||
|
|
||||||
Checklists.helpers({
|
Checklists.helpers({
|
||||||
itemCount() {
|
itemCount() {
|
||||||
return this.items.length;
|
return this.items.length;
|
||||||
},
|
},
|
||||||
|
getItems() {
|
||||||
|
return this.items.sort(function (itemA, itemB) {
|
||||||
|
if (itemA.sort < itemB.sort) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (itemA.sort > itemB.sort) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
finishedCount() {
|
finishedCount() {
|
||||||
return this.items.filter((item) => {
|
return this.items.filter((item) => {
|
||||||
return item.isFinished;
|
return item.isFinished;
|
||||||
|
|
@ -54,7 +80,8 @@ Checklists.helpers({
|
||||||
return _.findWhere(this.items, { _id });
|
return _.findWhere(this.items, { _id });
|
||||||
},
|
},
|
||||||
itemIndex(itemId) {
|
itemIndex(itemId) {
|
||||||
return _.pluck(this.items, '_id').indexOf(itemId);
|
const items = self.findOne({_id : this._id}).items;
|
||||||
|
return _.pluck(items, '_id').indexOf(itemId);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -86,14 +113,11 @@ Checklists.mutations({
|
||||||
//for items in checklist
|
//for items in checklist
|
||||||
addItem(title) {
|
addItem(title) {
|
||||||
const itemCount = this.itemCount();
|
const itemCount = this.itemCount();
|
||||||
let idx = 0;
|
const _id = `${this._id}${this.newItemIndex}`;
|
||||||
if (itemCount > 0) {
|
return {
|
||||||
const lastId = this.items[itemCount - 1]._id;
|
$addToSet: { items: { _id, title, isFinished: false, sort: itemCount } },
|
||||||
const lastIdSuffix = lastId.substr(this._id.length);
|
$set: { newItemIndex: this.newItemIndex + 1},
|
||||||
idx = parseInt(lastIdSuffix, 10) + 1;
|
};
|
||||||
}
|
|
||||||
const _id = `${this._id}${idx}`;
|
|
||||||
return { $addToSet: { items: { _id, title, isFinished: false } } };
|
|
||||||
},
|
},
|
||||||
removeItem(itemId) {
|
removeItem(itemId) {
|
||||||
return { $pull: { items: { _id: itemId } } };
|
return { $pull: { items: { _id: itemId } } };
|
||||||
|
|
@ -143,6 +167,21 @@ Checklists.mutations({
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
sortItems(itemIDs) {
|
||||||
|
const validItems = [];
|
||||||
|
for (const itemID of itemIDs) {
|
||||||
|
if (this.getItem(itemID)) {
|
||||||
|
validItems.push(this.itemIndex(itemID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const modifiedValues = {};
|
||||||
|
for (let i = 0; i < validItems.length; i++) {
|
||||||
|
modifiedValues[`items.${validItems[i]}.sort`] = i;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
$set: modifiedValues,
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Meteor.isServer) {
|
if (Meteor.isServer) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue