summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/components/lists/listBody.js98
1 files changed, 97 insertions, 1 deletions
diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js
index 2e00cb4f..9d6aab88 100644
--- a/client/components/lists/listBody.js
+++ b/client/components/lists/listBody.js
@@ -26,7 +26,7 @@ BlazeComponent.extendComponent({
const firstCardDom = this.find('.js-minicard:first');
const lastCardDom = this.find('.js-minicard:last');
const textarea = $(evt.currentTarget).find('textarea');
- const title = textarea.val();
+ let title = textarea.val();
const position = Blaze.getData(evt.currentTarget).position;
let sortIndex;
if (position === 'top') {
@@ -36,10 +36,41 @@ BlazeComponent.extendComponent({
}
if ($.trim(title)) {
+ // Parse for @user and #label mentions, stripping them from the title
+ // and applying the appropriate users and labels to the card instead.
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+
+ // Find all @-mentioned usernames, collect a list of their IDs
+ // and strip their mention out of the title.
+ let foundUserIds = [];
+ currentBoard.members.forEach(member => {
+ const username = Users.findOne(member.userId).username;
+ let nameNdx = title.indexOf('@' + username);
+ if(nameNdx !== -1) {
+ foundUserIds.push(member.userId);
+ title = title.substr(0, nameNdx) + title.substr(nameNdx + username.length + 1);
+ }
+ });
+
+ // Find all #-mentioned labels (based on their colour or name),
+ // collect a list of their IDs, and strip their mention out of
+ // the title.
+ let foundLabelIds = [];
+ currentBoard.labels.forEach(label => {
+ const labelName = (!label.name || label.name === "") ? label.color : label.name;
+ let labelNdx = title.indexOf('#' + labelName);
+ if(labelNdx !== -1) {
+ foundLabelIds.push(label._id);
+ title = title.substr(0, labelNdx) + title.substr(labelNdx + labelName.length + 1);
+ }
+ });
+
const _id = Cards.insert({
title,
listId: this.data()._id,
boardId: this.data().board()._id,
+ labelIds: foundLabelIds,
+ members: foundUserIds,
sort: sortIndex,
});
// In case the filter is active we need to add the newly inserted card in
@@ -100,12 +131,18 @@ BlazeComponent.extendComponent({
},
}).register('listBody');
+let dropdownMenuIsOpened = false;
BlazeComponent.extendComponent({
template() {
return 'addCardForm';
},
pressKey(evt) {
+ // don't do anything if the drop down is showing
+ if(dropDownIsOpened) {
+ return;
+ }
+
// Pressing Enter should submit the card
if (evt.keyCode === 13) {
evt.preventDefault();
@@ -140,4 +177,63 @@ BlazeComponent.extendComponent({
keydown: this.pressKey,
}];
},
+
+ onCreated() {
+ dropDownIsOpened = false;
+ },
+
+ onRendered() {
+ const $textarea = this.$('textarea');
+ $textarea.textcomplete([
+ // User mentions
+ {
+ match: /\B@(\w*)$/,
+ search(term, callback) {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ callback($.map(currentBoard.members, (member) => {
+ const username = Users.findOne(member.userId).username;
+ return username.indexOf(term) === 0 ? username : null;
+ }));
+ },
+ template(value) {
+ return value;
+ },
+ replace(username) {
+ return `@${username} `;
+ },
+ index: 1,
+ },
+
+ // Labels
+ {
+ match: /\B#(\w*)$/,
+ search(term, callback) {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ callback($.map(currentBoard.labels, (label) => {
+ const labelName = (!label.name || label.name === "") ? label.color : label.name;
+ return labelName.indexOf(term) === 0 ? labelName : null;
+ }));
+ },
+ template(value) {
+ return value;
+ },
+ replace(label) {
+ return `#${label} `;
+ },
+ index: 1,
+ },
+ ]);
+
+ // customize hooks for dealing with the dropdowns
+ $textarea.on({
+ 'textComplete:show'() {
+ dropDownIsOpened = true;
+ },
+ 'textComplete:hide'() {
+ Tracker.afterFlush(() => {
+ dropDownIsOpened = false;
+ });
+ },
+ });
+ },
}).register('addCardForm');