summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLauri Ojansivu <x@xet7.org>2017-09-13 20:28:11 +0300
committerLauri Ojansivu <x@xet7.org>2017-09-13 20:28:11 +0300
commit68897a77dc18a5bbdbc9cd9e4a84b4ef574e9dcc (patch)
tree9f361a4d3d632119b72dedd6c7b8c5ebbb90946b
parent3bb843182714c96c2427b6f3b70bb232f5f5639c (diff)
parentb7c7b936409c17cb829de9ccf078bee0ac485d0a (diff)
downloadwekan-68897a77dc18a5bbdbc9cd9e4a84b4ef574e9dcc.tar.gz
wekan-68897a77dc18a5bbdbc9cd9e4a84b4ef574e9dcc.tar.bz2
wekan-68897a77dc18a5bbdbc9cd9e4a84b4ef574e9dcc.zip
Merge branch 'frmwrk123-issue-876' into devel
Reorder checklists. Move checklist item to another checklist. Thanks to frmwrk123 ! Related #876
-rw-r--r--CHANGELOG.md8
-rw-r--r--client/components/cards/checklists.jade7
-rw-r--r--client/components/cards/checklists.js67
-rw-r--r--models/checklists.js57
4 files changed, 126 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1c5c3483..c3a6f551 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
This release adds the following new features:
diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade
index d04a9b60..7ecc5dd3 100644
--- a/client/components/cards/checklists.jade
+++ b/client/components/cards/checklists.jade
@@ -46,8 +46,8 @@ template(name="editChecklistItemForm")
a.js-delete-checklist-item {{_ "delete"}}...
template(name="checklistItems")
- .checklist-items
- each item in checklist.items
+ .checklist-items.js-checklist-items
+ each item in checklist.getItems
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
+editChecklistItemForm(type = 'item' item = item checklist = checklist)
else
@@ -61,11 +61,10 @@ template(name="checklistItems")
| {{_ 'add-checklist-item'}}...
template(name='itemDetail')
- .item
+ .item.js-checklist-item
if canModifyCard
.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}}
else
.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
.item-title(class="{{#if item.isFinished }}is-checked{{/if}}") {{item.title}}
-
diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js
index 24a78035..bd9d275a 100644
--- a/client/components/cards/checklists.js
+++ b/client/components/cards/checklists.js
@@ -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({
addChecklist(event) {
event.preventDefault();
const textarea = this.find('textarea.js-add-checklist-item');
const title = textarea.value.trim();
const cardId = this.currentData().cardId;
+ const card = Cards.findOne(cardId);
if (title) {
Checklists.insert({
cardId,
title,
+ sort: card.checklists().count(),
});
setTimeout(() => {
this.$('.add-checklist-item').last().click();
diff --git a/models/checklists.js b/models/checklists.js
index 2521412f..35ef8ae1 100644
--- a/models/checklists.js
+++ b/models/checklists.js
@@ -17,6 +17,10 @@ Checklists.attachSchema(new SimpleSchema({
'items.$.title': {
type: String,
},
+ 'items.$.sort': {
+ type: Number,
+ decimal: true,
+ },
'items.$.isFinished': {
type: Boolean,
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({
itemCount() {
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() {
return this.items.filter((item) => {
return item.isFinished;
@@ -54,7 +80,8 @@ Checklists.helpers({
return _.findWhere(this.items, { _id });
},
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
addItem(title) {
const itemCount = this.itemCount();
- let idx = 0;
- if (itemCount > 0) {
- const lastId = this.items[itemCount - 1]._id;
- const lastIdSuffix = lastId.substr(this._id.length);
- idx = parseInt(lastIdSuffix, 10) + 1;
- }
- const _id = `${this._id}${idx}`;
- return { $addToSet: { items: { _id, title, isFinished: false } } };
+ const _id = `${this._id}${this.newItemIndex}`;
+ return {
+ $addToSet: { items: { _id, title, isFinished: false, sort: itemCount } },
+ $set: { newItemIndex: this.newItemIndex + 1},
+ };
},
removeItem(itemId) {
return { $pull: { items: { _id: itemId } } };
@@ -143,6 +167,21 @@ Checklists.mutations({
}
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) {