diff --git a/client/src/components/activities/Activities/Item.jsx b/client/src/components/activities/Activities/Item.jsx index 7768f415..181e5970 100755 --- a/client/src/components/activities/Activities/Item.jsx +++ b/client/src/components/activities/Activities/Item.jsx @@ -84,6 +84,36 @@ const Item = React.memo(({ id }) => { break; } + case ActivityTypes.ADD_MEMBER_TO_CARD: + contentNode = + user.id === activity.data.user.id ? ( + + {userName} + {' joined this card'} + + ) : ( + + {userName} + + {' added '} + {activity.data.user.name} + {' to this card'} + + + ); + + break; default: contentNode = null; } diff --git a/client/src/components/notifications/NotificationsStep/Item.jsx b/client/src/components/notifications/NotificationsStep/Item.jsx index 7679fddc..69c65b5b 100644 --- a/client/src/components/notifications/NotificationsStep/Item.jsx +++ b/client/src/components/notifications/NotificationsStep/Item.jsx @@ -103,6 +103,24 @@ const Item = React.memo(({ id, onClose }) => { break; } + case NotificationTypes.ADD_MEMBER_TO_CARD: + contentNode = ( + + {creatorUserName} + {` added you to `} + + {cardName} + + + ); + + break; default: contentNode = null; } diff --git a/client/src/constants/Enums.js b/client/src/constants/Enums.js index 219d10b0..0cfcf20a 100755 --- a/client/src/constants/Enums.js +++ b/client/src/constants/Enums.js @@ -90,11 +90,13 @@ export const AttachmentTypes = { export const ActivityTypes = { CREATE_CARD: 'createCard', MOVE_CARD: 'moveCard', + ADD_MEMBER_TO_CARD: 'addMemberToCard', }; export const NotificationTypes = { MOVE_CARD: 'moveCard', COMMENT_CARD: 'commentCard', + ADD_MEMBER_TO_CARD: 'addMemberToCard', }; export const NotificationServiceFormats = { diff --git a/client/src/locales/en-GB/core.js b/client/src/locales/en-GB/core.js index f5c256d8..d19b63a2 100644 --- a/client/src/locales/en-GB/core.js +++ b/client/src/locales/en-GB/core.js @@ -287,6 +287,9 @@ export default { uploadedImages: 'Uploaded images', userActions_title: 'User Actions', userAddedThisCardToList: '<0>{{user}}<1> added this card to {{list}}', + userAddedUserToThisCard: '<0>{{actorUser}}<1> added {{addedUser}} to this card', + userAddedYouToCard: '{{user}} added you to <2>{{card}}', + userJoinedThisCard: `<0>{{user}}<1> joined this card`, userLeftNewCommentToCard: '{{user}} left a new comment «{{comment}}» to <2>{{card}}', userMovedCardFromListToList: '{{user}} moved <2>{{card}} from {{fromList}} to {{toList}}', userMovedThisCardFromListToList: diff --git a/client/src/locales/en-US/core.js b/client/src/locales/en-US/core.js index 0b0345e8..468eb945 100644 --- a/client/src/locales/en-US/core.js +++ b/client/src/locales/en-US/core.js @@ -282,6 +282,9 @@ export default { uploadedImages: 'Uploaded images', userActions_title: 'User Actions', userAddedThisCardToList: '<0>{{user}}<1> added this card to {{list}}', + userAddedUserToThisCard: '<0>{{actorUser}}<1> added {{addedUser}} to this card', + userAddedYouToCard: '{{user}} added you to <2>{{card}}', + userJoinedThisCard: `<0>{{user}}<1> joined this card`, userLeftNewCommentToCard: '{{user}} left a new comment «{{comment}}» to <2>{{card}}', userMovedCardFromListToList: '{{user}} moved <2>{{card}} from {{fromList}} to {{toList}}', userMovedThisCardFromListToList: diff --git a/server/api/controllers/card-memberships/create.js b/server/api/controllers/card-memberships/create.js index 5d3aa4c7..c5750764 100755 --- a/server/api/controllers/card-memberships/create.js +++ b/server/api/controllers/card-memberships/create.js @@ -67,7 +67,13 @@ module.exports = { throw Errors.NOT_ENOUGH_RIGHTS; } - const isBoardMember = await sails.helpers.users.isBoardMember(inputs.userId, board.id); + const user = await User.qm.getOneById(inputs.userId); + + if (!user) { + throw Errors.USER_NOT_FOUND; + } + + const isBoardMember = await sails.helpers.users.isBoardMember(user.id, board.id); if (!isBoardMember) { throw Errors.USER_NOT_FOUND; @@ -80,7 +86,7 @@ module.exports = { list, values: { card, - userId: inputs.userId, + user, }, actorUser: currentUser, request: this.req, diff --git a/server/api/helpers/actions/create-one.js b/server/api/helpers/actions/create-one.js index 8aa73fd3..ca23d358 100644 --- a/server/api/helpers/actions/create-one.js +++ b/server/api/helpers/actions/create-one.js @@ -143,55 +143,76 @@ module.exports = { }); if (action.type !== Action.Types.CREATE_CARD) { - const cardSubscriptionUserIds = await sails.helpers.cards.getSubscriptionUserIds( - action.cardId, - action.userId, - ); - - const boardSubscriptionUserIds = await sails.helpers.boards.getSubscriptionUserIds( - inputs.board.id, - action.userId, - ); - - const notifiableUserIds = _.union(cardSubscriptionUserIds, boardSubscriptionUserIds); - - await Promise.all( - notifiableUserIds.map((userId) => - sails.helpers.notifications.createOne.with({ + if (action.type === Action.Types.ADD_MEMBER_TO_CARD) { + if (values.user !== action.data.user.id) { + await sails.helpers.notifications.createOne.with({ values: { - userId, action, type: action.type, data: { ...action.data, card: _.pick(values.card, ['name']), }, + userId: action.data.user.id, creatorUser: values.user, card: values.card, }, project: inputs.project, board: inputs.board, list: inputs.list, - }), - ), - ); - } + }); + } + } else { + const cardSubscriptionUserIds = await sails.helpers.cards.getSubscriptionUserIds( + action.cardId, + action.userId, + ); - const notificationServices = await NotificationService.qm.getByBoardId(inputs.board.id); + const boardSubscriptionUserIds = await sails.helpers.boards.getSubscriptionUserIds( + inputs.board.id, + action.userId, + ); - if (notificationServices.length > 0) { - const services = notificationServices.map((notificationService) => - _.pick(notificationService, ['url', 'format']), - ); + const notifiableUserIds = _.union(cardSubscriptionUserIds, boardSubscriptionUserIds); - buildAndSendNotifications( - services, - inputs.board, - values.card, - action, - values.user, - sails.helpers.utils.makeTranslator(), - ); + await Promise.all( + notifiableUserIds.map((userId) => + sails.helpers.notifications.createOne.with({ + values: { + userId, + action, + type: action.type, + data: { + ...action.data, + card: _.pick(values.card, ['name']), + }, + creatorUser: values.user, + card: values.card, + }, + project: inputs.project, + board: inputs.board, + list: inputs.list, + }), + ), + ); + + const notificationServices = await NotificationService.qm.getByBoardId(inputs.board.id); + + if (notificationServices.length > 0) { + const services = notificationServices.map((notificationService) => + _.pick(notificationService, ['url', 'format']), + ); + + buildAndSendNotifications( + services, + inputs.board, + values.card, + action, + values.user, + sails.helpers.utils.makeTranslator(), + ); + } + } } return action; diff --git a/server/api/helpers/card-memberships/create-one.js b/server/api/helpers/card-memberships/create-one.js index bb41285e..b66fd2fb 100644 --- a/server/api/helpers/card-memberships/create-one.js +++ b/server/api/helpers/card-memberships/create-one.js @@ -37,15 +37,12 @@ module.exports = { async fn(inputs) { const { values } = inputs; - if (values.user) { - values.userId = values.user.id; - } - let cardMembership; try { cardMembership = await CardMembership.qm.createOne({ ...values, cardId: values.card.id, + userId: values.user.id, }); } catch (error) { if (error.code === 'E_UNIQUE') { @@ -69,6 +66,7 @@ module.exports = { buildData: () => ({ item: cardMembership, included: { + users: [values.user], projects: [inputs.project], boards: [inputs.board], lists: [inputs.list], @@ -107,6 +105,20 @@ module.exports = { // TODO: send webhooks } + await sails.helpers.actions.createOne.with({ + values: { + type: Action.Types.ADD_MEMBER_TO_CARD, + data: { + user: _.pick(values.user, ['id', 'name']), + }, + user: inputs.actorUser, + card: values.card, + }, + project: inputs.project, + board: inputs.board, + list: inputs.list, + }); + return cardMembership; }, }; diff --git a/server/api/helpers/notifications/create-one.js b/server/api/helpers/notifications/create-one.js index 63ff59f1..990e6a41 100644 --- a/server/api/helpers/notifications/create-one.js +++ b/server/api/helpers/notifications/create-one.js @@ -12,6 +12,8 @@ const buildTitle = (notification, t) => { return t('Card Moved'); case Notification.Types.COMMENT_CARD: return t('New Comment'); + case Notification.Types.ADD_MEMBER_TO_CARD: + return t('You Were Added to Card'); default: return null; } @@ -77,6 +79,22 @@ const buildBodyByFormat = (board, card, notification, actorUser, t) => { )}:\n\n${escapeHtml(commentText)}`, }; } + case Notification.Types.ADD_MEMBER_TO_CARD: + return { + text: t('%s added you to %s on %s', actorUser.name, card.name, board.name), + markdown: t( + '%s added you to %s on %s', + escapeMarkdown(actorUser.name), + markdownCardLink, + escapeMarkdown(board.name), + ), + html: t( + '%s added you to %s on %s', + escapeHtml(actorUser.name), + htmlCardLink, + escapeHtml(board.name), + ), + }; default: return null; } @@ -120,6 +138,15 @@ const buildAndSendEmail = async (board, card, notification, actorUser, notifiabl boardLink, )}

${escapeHtml(notification.data.text)}

`; + break; + case Notification.Types.ADD_MEMBER_TO_CARD: + html = `

${t( + '%s added you to %s on %s', + escapeHtml(actorUser.name), + cardLink, + boardLink, + )}

`; + break; default: return; diff --git a/server/api/models/Action.js b/server/api/models/Action.js index 59921b45..6fd8711f 100755 --- a/server/api/models/Action.js +++ b/server/api/models/Action.js @@ -13,6 +13,7 @@ const Types = { CREATE_CARD: 'createCard', MOVE_CARD: 'moveCard', + ADD_MEMBER_TO_CARD: 'addMemberToCard', }; module.exports = { diff --git a/server/api/models/Notification.js b/server/api/models/Notification.js index c970d7dd..2fdfde03 100755 --- a/server/api/models/Notification.js +++ b/server/api/models/Notification.js @@ -13,6 +13,7 @@ const Types = { MOVE_CARD: 'moveCard', COMMENT_CARD: 'commentCard', + ADD_MEMBER_TO_CARD: 'addMemberToCard', }; module.exports = { diff --git a/server/config/locales/en-GB.json b/server/config/locales/en-GB.json index 30d4f65b..9e9c1322 100644 --- a/server/config/locales/en-GB.json +++ b/server/config/locales/en-GB.json @@ -6,6 +6,8 @@ "This is a test text message!": "This is a test text message!", "This is a *test* **markdown** `message`!": "This is a *test* **markdown** `message`!", "This is a test html message": "This is a test html message", + "You Were Added to Card": "Your Were Added to Card", + "%s added you to %s on %s": "%s added you to %s on %s", "%s created %s in %s on %s": "%s created %s in %s on %s", "%s left a new comment to %s on %s": "%s left a new comment to %s on %s", "%s moved %s from %s to %s on %s": "%s moved %s from %s to %s on %s" diff --git a/server/config/locales/en-US.json b/server/config/locales/en-US.json index c5190d91..f9b9b376 100644 --- a/server/config/locales/en-US.json +++ b/server/config/locales/en-US.json @@ -6,6 +6,8 @@ "This is a test text message!": "This is a test text message!", "This is a *test* **markdown** `message`!": "This is a *test* **markdown** `message`!", "This is a test html message": "This is a test html message", + "You Were Added to Card": "Your Were Added to Card", + "%s added you to %s on %s": "%s added you to %s on %s", "%s created %s in %s on %s": "%s created %s in %s on %s", "%s left a new comment to %s on %s": "%s left a new comment to %s on %s", "%s moved %s from %s to %s on %s": "%s moved %s from %s to %s on %s" diff --git a/server/config/locales/ru-RU.json b/server/config/locales/ru-RU.json index bc6bebd2..6f300160 100644 --- a/server/config/locales/ru-RU.json +++ b/server/config/locales/ru-RU.json @@ -6,6 +6,8 @@ "This is a test text message!": "Это тестовое сообщение!", "This is a *test* **markdown** `message`!": "Это *тестовое* **markdown** `сообщение`!", "This is a test html message": "Это тестовое html сообщение", + "You Were Added to Card": "Вы были добавлены к карточке", + "%s added you to %s on %s": "%s добавил(а) вас к %s на %s", "%s created %s in %s on %s": "%s создал(а) %s в %s на %s", "%s left a new comment to %s on %s": "%s оставил(а) новый комментарий к %s на %s", "%s moved %s from %s to %s on %s": "%s переместил(а) %s из %s в %s на %s"