mirror of https://github.com/wekan/wekan
Merge branch 'ckls' of https://github.com/lkisme/wekan into lkisme-ckls
commit
1cf9b1be4e
@ -0,0 +1,61 @@ |
||||
template(name="checklists") |
||||
h2 {{_ 'checklists'}} |
||||
.card-checklist-items |
||||
each checklist in currentCard.checklists |
||||
+checklistDetail(checklist = checklist) |
||||
+inlinedForm(classNames="js-add-checklist" cardId = cardId) |
||||
+addChecklistItemForm |
||||
else |
||||
a.js-open-inlined-form |
||||
i.fa.fa-plus |
||||
| {{_ 'add-checklist'}}... |
||||
|
||||
template(name="checklistDetail") |
||||
+inlinedForm(classNames="js-edit-checklist-title") |
||||
+editChecklistItemForm(checklist = checklist) |
||||
else |
||||
.checklist-title |
||||
.checkbox.fa.fa-check-square-o |
||||
a.js-delete-checklist {{_ "delete"}}... |
||||
span.checklist-stat(class="{{#if checklist.isFinished}}is-finished{{/if}}") {{checklist.finishedCount}}/{{checklist.itemCount}} |
||||
h2.title.js-open-inlined-form.is-editable {{checklist.title}} |
||||
+checklistItems(checklist = checklist) |
||||
|
||||
template(name="addChecklistItemForm") |
||||
textarea.js-add-checklist-item(rows='1' autofocus) |
||||
.edit-controls.clearfix |
||||
button.primary.confirm.js-submit-add-checklist-item-form(type="submit") {{_ 'save'}} |
||||
a.fa.fa-times-thin.js-close-inlined-form |
||||
|
||||
template(name="editChecklistItemForm") |
||||
textarea.js-edit-checklist-item(rows='1' autofocus) |
||||
if $eq type 'item' |
||||
= item.title |
||||
else |
||||
= checklist.title |
||||
.edit-controls.clearfix |
||||
button.primary.confirm.js-submit-edit-checklist-item-form(type="submit") {{_ 'save'}} |
||||
a.fa.fa-times-thin.js-close-inlined-form |
||||
span(title=createdAt) {{ moment createdAt }} |
||||
if currentUser.isBoardMember |
||||
a.js-delete-checklist-item {{_ "delete"}}... |
||||
|
||||
template(name="checklistItems") |
||||
.checklist-items |
||||
each item in checklist.items |
||||
+inlinedForm(classNames="js-edit-checklist-item") |
||||
+editChecklistItemForm(type = 'item' item = item checklist = checklist) |
||||
else |
||||
+itemDetail(item = item checklist = checklist) |
||||
if currentUser.isBoardMember |
||||
+inlinedForm(classNames="js-add-checklist-item" checklist = checklist) |
||||
+addChecklistItemForm |
||||
else |
||||
a.add-checklist-item.js-open-inlined-form |
||||
i.fa.fa-plus |
||||
| {{_ 'add-checklist-item'}}... |
||||
|
||||
template(name='itemDetail') |
||||
.item |
||||
.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}} |
@ -0,0 +1,74 @@ |
||||
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; |
||||
Checklists.insert({ |
||||
cardId, |
||||
title, |
||||
}); |
||||
}, |
||||
|
||||
addChecklistItem(event) { |
||||
event.preventDefault(); |
||||
const textarea = this.find('textarea.js-add-checklist-item'); |
||||
const title = textarea.value.trim(); |
||||
const checklist = this.currentData().checklist; |
||||
checklist.addItem(title); |
||||
}, |
||||
|
||||
editChecklist(event) { |
||||
event.preventDefault(); |
||||
const textarea = this.find('textarea.js-edit-checklist-item'); |
||||
const title = textarea.value.trim(); |
||||
const checklist = this.currentData().checklist; |
||||
checklist.setTitle(title); |
||||
}, |
||||
|
||||
editChecklistItem(event) { |
||||
event.preventDefault(); |
||||
|
||||
const textarea = this.find('textarea.js-edit-checklist-item'); |
||||
const title = textarea.value.trim(); |
||||
const itemId = this.currentData().item._id; |
||||
const checklist = this.currentData().checklist; |
||||
checklist.editItem(itemId, title); |
||||
}, |
||||
|
||||
deleteItem() { |
||||
const checklist = this.currentData().checklist; |
||||
const item = this.currentData().item; |
||||
if (checklist && item && item._id) { |
||||
checklist.removeItem(item._id); |
||||
} |
||||
}, |
||||
|
||||
deleteChecklist() { |
||||
const checklist = this.currentData().checklist; |
||||
if (checklist && checklist._id) { |
||||
Checklists.remove(checklist._id); |
||||
} |
||||
}, |
||||
|
||||
pressKey(event) { |
||||
//If user press enter key inside a form, submit it, so user doesn't have to leave keyboard to submit a form.
|
||||
if (event.keyCode === 13) { |
||||
event.preventDefault(); |
||||
const $form = $(event.currentTarget).closest('form'); |
||||
$form.find('button[type=submit]').click(); |
||||
} |
||||
}, |
||||
|
||||
events() { |
||||
return [{ |
||||
'submit .js-add-checklist': this.addChecklist, |
||||
'submit .js-edit-checklist-title': this.editChecklist, |
||||
'submit .js-add-checklist-item': this.addChecklistItem, |
||||
'submit .js-edit-checklist-item': this.editChecklistItem, |
||||
'click .js-delete-checklist-item': this.deleteItem, |
||||
'click .js-delete-checklist': this.deleteChecklist, |
||||
keydown: this.pressKey, |
||||
}]; |
||||
}, |
||||
}).register('checklists'); |
@ -0,0 +1,68 @@ |
||||
.js-add-checklist |
||||
color: #8c8c8c |
||||
|
||||
textarea.js-add-checklist-item, textarea.js-edit-checklist-item |
||||
overflow: hidden |
||||
word-wrap: break-word |
||||
resize: none |
||||
height: 34px |
||||
|
||||
.delete-text |
||||
color: #8c8c8c |
||||
text-decoration: underline |
||||
word-wrap: break-word |
||||
float: right |
||||
padding-top: 6px |
||||
&:hover |
||||
color: inherit |
||||
|
||||
.checklist-title |
||||
.checkbox |
||||
float: left |
||||
width: 30px |
||||
height 30px |
||||
font-size: 18px |
||||
line-height: 30px |
||||
|
||||
.title |
||||
font-size: 18px |
||||
line-height: 30px |
||||
|
||||
.checklist-stat |
||||
margin: 0 0.5em |
||||
float: right |
||||
padding-top: 6px |
||||
&.is-finished |
||||
color: #3cb500 |
||||
|
||||
.js-delete-checklist |
||||
@extends .delete-text |
||||
|
||||
.checklist-items |
||||
margin: 0 0 0.5em 1.33em |
||||
|
||||
.item |
||||
line-height: 25px |
||||
font-size: 1.1em |
||||
margin-top: 3px |
||||
display: flex |
||||
|
||||
.check-box |
||||
margin-top: 5px |
||||
&.is-checked |
||||
border-bottom: 2px solid #3cb500 |
||||
border-right: 2px solid #3cb500 |
||||
|
||||
.item-title |
||||
padding-left: 10px; |
||||
&.is-checked |
||||
color: #8c8c8c |
||||
font-style: italic |
||||
|
||||
.js-delete-checklist-item |
||||
@extends .delete-text |
||||
padding: 12px 0 0 0 |
||||
|
||||
.add-checklist-item |
||||
padding-top: 0.5em |
||||
display: inline-block |
@ -0,0 +1,164 @@ |
||||
Checklists = new Mongo.Collection('checklists'); |
||||
|
||||
Checklists.attachSchema(new SimpleSchema({ |
||||
cardId: { |
||||
type: String, |
||||
}, |
||||
title: { |
||||
type: String, |
||||
}, |
||||
items: { |
||||
type: [Object], |
||||
defaultValue: [], |
||||
}, |
||||
'items.$._id': { |
||||
type: String, |
||||
}, |
||||
'items.$.title': { |
||||
type: String, |
||||
}, |
||||
'items.$.isFinished': { |
||||
type: Boolean, |
||||
defaultValue: false, |
||||
}, |
||||
finishedAt: { |
||||
type: Date, |
||||
optional: true, |
||||
}, |
||||
createdAt: { |
||||
type: Date, |
||||
denyUpdate: false, |
||||
}, |
||||
})); |
||||
|
||||
Checklists.helpers({ |
||||
itemCount () { |
||||
return this.items.length; |
||||
}, |
||||
finishedCount () { |
||||
return this.items.filter((item) => { |
||||
return item.isFinished; |
||||
}).length; |
||||
}, |
||||
isFinished () { |
||||
return 0 !== this.itemCount() && this.itemCount() === this.finishedCount(); |
||||
}, |
||||
getItem (_id) { |
||||
return _.findWhere(this.items, { _id }); |
||||
}, |
||||
itemIndex(itemId) { |
||||
return _.pluck(this.items, '_id').indexOf(itemId); |
||||
}, |
||||
}); |
||||
|
||||
Checklists.allow({ |
||||
insert(userId, doc) { |
||||
return allowIsBoardMemberByCard(userId, Cards.findOne(doc.cardId)); |
||||
}, |
||||
update(userId, doc) { |
||||
return allowIsBoardMemberByCard(userId, Cards.findOne(doc.cardId)); |
||||
}, |
||||
remove(userId, doc) { |
||||
return allowIsBoardMemberByCard(userId, Cards.findOne(doc.cardId)); |
||||
}, |
||||
fetch: ['userId', 'cardId'], |
||||
}); |
||||
|
||||
Checklists.before.insert((userId, doc) => { |
||||
doc.createdAt = new Date(); |
||||
if (!doc.userId) { |
||||
doc.userId = userId; |
||||
} |
||||
}); |
||||
|
||||
Checklists.mutations({ |
||||
//for checklist itself
|
||||
setTitle(title){ |
||||
return { $set: { title }}; |
||||
}, |
||||
//for items in checklist
|
||||
addItem(title) { |
||||
const itemCount = this.itemCount(); |
||||
const _id = `${this._id}${itemCount}`; |
||||
return { $addToSet: {items: {_id, title, isFinished: false}} }; |
||||
}, |
||||
removeItem(itemId) { |
||||
return {$pull: {items: {_id : itemId}}}; |
||||
}, |
||||
editItem(itemId, title) { |
||||
if (this.getItem(itemId)) { |
||||
const itemIndex = this.itemIndex(itemId); |
||||
return { |
||||
$set: { |
||||
[`items.${itemIndex}.title`]: title, |
||||
}, |
||||
}; |
||||
} |
||||
return {}; |
||||
}, |
||||
finishItem(itemId) { |
||||
if (this.getItem(itemId)) { |
||||
const itemIndex = this.itemIndex(itemId); |
||||
return { |
||||
$set: { |
||||
[`items.${itemIndex}.isFinished`]: true, |
||||
}, |
||||
}; |
||||
} |
||||
return {}; |
||||
}, |
||||
resumeItem(itemId) { |
||||
if (this.getItem(itemId)) { |
||||
const itemIndex = this.itemIndex(itemId); |
||||
return { |
||||
$set: { |
||||
[`items.${itemIndex}.isFinished`]: false, |
||||
}, |
||||
}; |
||||
} |
||||
return {}; |
||||
}, |
||||
toggleItem(itemId) { |
||||
const item = this.getItem(itemId); |
||||
if (item) { |
||||
const itemIndex = this.itemIndex(itemId); |
||||
return { |
||||
$set: { |
||||
[`items.${itemIndex}.isFinished`]: !item.isFinished, |
||||
}, |
||||
}; |
||||
} |
||||
return {}; |
||||
}, |
||||
}); |
||||
|
||||
if (Meteor.isServer) { |
||||
Checklists.after.insert((userId, doc) => { |
||||
Activities.insert({ |
||||
userId, |
||||
activityType: 'addChecklist', |
||||
cardId: doc.cardId, |
||||
boardId: Cards.findOne(doc.cardId).boardId, |
||||
checklistId: doc._id, |
||||
}); |
||||
}); |
||||
|
||||
//TODO: so there will be no activity for adding item into checklist, maybe will be implemented in the future.
|
||||
// Checklists.after.update((userId, doc) => {
|
||||
// console.log('update:', doc)
|
||||
// Activities.insert({
|
||||
// userId,
|
||||
// activityType: 'addChecklist',
|
||||
// boardId: doc.boardId,
|
||||
// cardId: doc.cardId,
|
||||
// checklistId: doc._id,
|
||||
// });
|
||||
// });
|
||||
|
||||
Checklists.before.remove((userId, doc) => { |
||||
const activity = Activities.findOne({ checklistId: doc._id }); |
||||
if (activity) { |
||||
Activities.remove(activity._id); |
||||
} |
||||
}); |
||||
} |
Loading…
Reference in new issue