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.$.sort' : {
type : Number ,
decimal : true ,
} ,
'items.$.isFinished' : {
type : Boolean ,
defaultValue : false ,
} ,
finishedAt : {
type : Date ,
optional : true ,
} ,
createdAt : {
type : Date ,
denyUpdate : false ,
autoValue ( ) { // eslint-disable-line consistent-return
if ( this . isInsert ) {
return new Date ( ) ;
} else {
this . unset ( ) ;
}
} ,
} ,
sort : {
type : Number ,
decimal : true ,
} ,
} ) ) ;
const self = Checklists ;
Checklists . helpers ( {
itemCount ( ) {
return this . items . length ;
} ,
getItemsSorted ( ) {
return _ . sortBy ( this . items , 'sort' ) ;
} ,
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 ) {
const items = self . findOne ( { _id : this . _id } ) . items ;
return _ . pluck ( items , '_id' ) . indexOf ( itemId ) ;
} ,
getNewItemId ( ) {
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 ;
}
return ` ${ this . _id } ${ idx } ` ;
} ,
} ) ;
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 _id = this . getNewItemId ( ) ;
return {
$addToSet : {
items : {
_id , title ,
isFinished : false ,
sort : this . itemCount ( ) ,
} ,
} ,
} ;
} ,
addFullItem ( item ) {
const itemsUpdate = { } ;
this . items . forEach ( function ( iterItem , index ) {
if ( iterItem . sort >= item . sort ) {
itemsUpdate [ ` items. ${ index } .sort ` ] = iterItem . sort + 1 ;
}
} ) ;
if ( ! _ . isEmpty ( itemsUpdate ) ) {
self . direct . update ( { _id : this . _id } , { $set : itemsUpdate } ) ;
}
return { $addToSet : { items : item } } ;
} ,
removeItem ( itemId ) {
const item = this . getItem ( itemId ) ;
const itemsUpdate = { } ;
this . items . forEach ( function ( iterItem , index ) {
if ( iterItem . sort > item . sort ) {
itemsUpdate [ ` items. ${ index } .sort ` ] = iterItem . sort - 1 ;
}
} ) ;
if ( ! _ . isEmpty ( itemsUpdate ) ) {
self . direct . update ( { _id : this . _id } , { $set : itemsUpdate } ) ;
}
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 { } ;
} ,
sortItems ( itemIDs ) {
const validItems = [ ] ;
itemIDs . forEach ( ( itemID ) => {
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 ) {
Meteor . startup ( ( ) => {
Checklists . _collection . _ensureIndex ( { cardId : 1 , createdAt : 1 } ) ;
} ) ;
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.
// The future is now
Checklists . after . update ( ( userId , doc , fieldNames , modifier ) => {
if ( fieldNames . includes ( 'items' ) ) {
if ( modifier . $addToSet ) {
Activities . insert ( {
userId ,
activityType : 'addChecklistItem' ,
cardId : doc . cardId ,
boardId : Cards . findOne ( doc . cardId ) . boardId ,
checklistId : doc . _id ,
checklistItemId : modifier . $addToSet . items . _id ,
} ) ;
} else if ( modifier . $pull ) {
const activity = Activities . findOne ( {
checklistItemId : modifier . $pull . items . _id ,
} ) ;
if ( activity ) {
Activities . remove ( activity . _id ) ;
}
}
}
} ) ;
Checklists . before . remove ( ( userId , doc ) => {
const activities = Activities . find ( { checklistId : doc . _id } ) ;
if ( activities ) {
activities . forEach ( ( activity ) => {
Activities . remove ( activity . _id ) ;
} ) ;
}
} ) ;
}
//CARD COMMENT REST API
if ( Meteor . isServer ) {
JsonRoutes . add ( 'GET' , '/api/boards/:boardId/cards/:cardId/checklists' , function ( req , res , next ) {
try {
Authentication . checkUserId ( req . userId ) ;
const paramCardId = req . params . cardId ;
JsonRoutes . sendResult ( res , {
code : 200 ,
data : Checklists . find ( { cardId : paramCardId } ) . map ( function ( doc ) {
return {
_id : doc . _id ,
title : doc . title ,
} ;
} ) ,
} ) ;
}
catch ( error ) {
JsonRoutes . sendResult ( res , {
code : 200 ,
data : error ,
} ) ;
}
} ) ;
JsonRoutes . add ( 'GET' , '/api/boards/:boardId/cards/:cardId/checklists/:checklistId' , function ( req , res , next ) {
try {
Authentication . checkUserId ( req . userId ) ;
const paramChecklistId = req . params . checklistId ;
const paramCardId = req . params . cardId ;
JsonRoutes . sendResult ( res , {
code : 200 ,
data : Checklists . findOne ( { _id : paramChecklistId , cardId : paramCardId } ) ,
} ) ;
}
catch ( error ) {
JsonRoutes . sendResult ( res , {
code : 200 ,
data : error ,
} ) ;
}
} ) ;
JsonRoutes . add ( 'POST' , '/api/boards/:boardId/cards/:cardId/checklists' , function ( req , res , next ) {
try {
Authentication . checkUserId ( req . userId ) ;
const paramCardId = req . params . cardId ;
const checklistToSend = { } ;
checklistToSend . cardId = paramCardId ;
checklistToSend . title = req . body . title ;
checklistToSend . items = [ ] ;
const id = Checklists . insert ( checklistToSend ) ;
const checklist = Checklists . findOne ( { _id : id } ) ;
req . body . items . forEach ( function ( item ) {
checklist . addItem ( item ) ;
} , this ) ;
JsonRoutes . sendResult ( res , {
code : 200 ,
data : {
_id : id ,
} ,
} ) ;
}
catch ( error ) {
JsonRoutes . sendResult ( res , {
code : 200 ,
data : error ,
} ) ;
}
} ) ;
JsonRoutes . add ( 'DELETE' , '/api/boards/:boardId/cards/:cardId/checklists/:checklistId' , function ( req , res , next ) {
try {
Authentication . checkUserId ( req . userId ) ;
const paramCommentId = req . params . commentId ;
const paramCardId = req . params . cardId ;
Checklists . remove ( { _id : paramCommentId , cardId : paramCardId } ) ;
JsonRoutes . sendResult ( res , {
code : 200 ,
data : {
_id : paramCardId ,
} ,
} ) ;
}
catch ( error ) {
JsonRoutes . sendResult ( res , {
code : 200 ,
data : error ,
} ) ;
}
} ) ;
}