Fix list view issues. Allow creation of boards from templates

This commit is contained in:
Andrés Manelli 2019-02-25 22:48:25 +01:00
parent 13c2157e36
commit dc7286a0ef
12 changed files with 122 additions and 35 deletions

View file

@ -27,7 +27,7 @@ template(name="boardBody")
each currentBoard.swimlanes each currentBoard.swimlanes
+swimlane(this) +swimlane(this)
else if isViewLists else if isViewLists
+listsGroup +listsGroup(currentBoard)
else if isViewCalendar else if isViewCalendar
+calendarView +calendarView

View file

@ -277,7 +277,10 @@ template(name="createBoard")
input.primary.wide(type="submit" value="{{_ 'create'}}") input.primary.wide(type="submit" value="{{_ 'create'}}")
span.quiet span.quiet
| {{_ 'or'}} | {{_ 'or'}}
a.js-import-board {{_ 'import-board'}} a.js-import-board {{_ 'import'}}
span.quiet
| /
a.js-board-template {{_ 'template'}}
template(name="chooseBoardSource") template(name="chooseBoardSource")
ul.pop-over-list ul.pop-over-list

View file

@ -304,6 +304,7 @@ const CreateBoard = BlazeComponent.extendComponent({
'click .js-import': Popup.open('boardImportBoard'), 'click .js-import': Popup.open('boardImportBoard'),
submit: this.onSubmit, submit: this.onSubmit,
'click .js-import-board': Popup.open('chooseBoardSource'), 'click .js-import-board': Popup.open('chooseBoardSource'),
'click .js-board-template': Popup.open('searchElement'),
}]; }];
}, },
}).register('createBoardPopup'); }).register('createBoardPopup');

View file

@ -0,0 +1,8 @@
template(name="miniboard")
.minicard(
class="minicard-{{colorClass}}")
.minicard-title
.handle
.fa.fa-arrows
+viewer
= title

View file

@ -103,16 +103,23 @@ template(name="searchElementPopup")
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus) input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus)
.list-body.js-perfect-scrollbar.search-card-results .list-body.js-perfect-scrollbar.search-card-results
.minicards.clearfix.js-minicards .minicards.clearfix.js-minicards
each results if isBoardTemplateSearch
if isListTemplateSearch each results
a.minicard-wrapper.js-minicard
+miniboard(this)
if isListTemplateSearch
each results
a.minicard-wrapper.js-minicard a.minicard-wrapper.js-minicard
+minilist(this) +minilist(this)
if isSwimlaneTemplateSearch if isSwimlaneTemplateSearch
each results
a.minicard-wrapper.js-minicard a.minicard-wrapper.js-minicard
+miniswimlane(this) +miniswimlane(this)
if isCardTemplateSearch if isCardTemplateSearch
each results
a.minicard-wrapper.js-minicard a.minicard-wrapper.js-minicard
+minicard(this) +minicard(this)
unless isTemplateSearch unless isTemplateSearch
each results
a.minicard-wrapper.js-minicard a.minicard-wrapper.js-minicard
+minicard(this) +minicard(this)

View file

@ -527,7 +527,11 @@ BlazeComponent.extendComponent({
this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-card-template'); this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-card-template');
this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-list-template'); this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-list-template');
this.isSwimlaneTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-open-add-swimlane-menu'); this.isSwimlaneTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-open-add-swimlane-menu');
this.isTemplateSearch = this.isCardTemplateSearch || this.isListTemplateSearch || this.isSwimlaneTemplateSearch; this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-add-board');
this.isTemplateSearch = this.isCardTemplateSearch ||
this.isListTemplateSearch ||
this.isSwimlaneTemplateSearch ||
this.isBoardTemplateSearch;
let board = {}; let board = {};
if (this.isTemplateSearch) { if (this.isTemplateSearch) {
board = Boards.findOne(Meteor.user().profile.templatesBoardId); board = Boards.findOne(Meteor.user().profile.templatesBoardId);
@ -548,23 +552,26 @@ BlazeComponent.extendComponent({
subManager.subscribe('board', boardId); subManager.subscribe('board', boardId);
this.selectedBoardId = new ReactiveVar(boardId); this.selectedBoardId = new ReactiveVar(boardId);
this.boardId = Session.get('currentBoard'); if (!this.isBoardTemplateSearch) {
// In order to get current board info this.boardId = Session.get('currentBoard');
subManager.subscribe('board', this.boardId); // In order to get current board info
// List where to insert card subManager.subscribe('board', this.boardId);
const list = $(Popup._getTopStack().openerElement).closest('.js-list'); this.swimlaneId = '';
this.listId = Blaze.getData(list[0])._id; // Swimlane where to insert card
// Swimlane where to insert card const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane');
const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane'); if (Meteor.user().profile.boardView === 'board-view-swimlanes')
this.swimlaneId = ''; this.swimlaneId = Blaze.getData(swimlane[0])._id;
if (Meteor.user().profile.boardView === 'board-view-swimlanes') else
this.swimlaneId = Blaze.getData(swimlane[0])._id; this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
else // List where to insert card
this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id; const list = $(Popup._getTopStack().openerElement).closest('.js-list');
this.listId = Blaze.getData(list[0])._id;
}
this.term = new ReactiveVar(''); this.term = new ReactiveVar('');
}, },
boards() { boards() {
console.log('booom');
const boards = Boards.find({ const boards = Boards.find({
archived: false, archived: false,
'members.userId': Meteor.userId(), 'members.userId': Meteor.userId(),
@ -587,6 +594,12 @@ BlazeComponent.extendComponent({
return board.searchLists(this.term.get()); return board.searchLists(this.term.get());
} else if (this.isSwimlaneTemplateSearch) { } else if (this.isSwimlaneTemplateSearch) {
return board.searchSwimlanes(this.term.get()); return board.searchSwimlanes(this.term.get());
} else if (this.isBoardTemplateSearch) {
const boards = board.searchBoards(this.term.get());
boards.forEach((board) => {
subManager.subscribe('board', board.linkedId);
});
return boards;
} else { } else {
return []; return [];
} }
@ -605,11 +618,11 @@ BlazeComponent.extendComponent({
'click .js-minicard'(evt) { 'click .js-minicard'(evt) {
// 0. Common // 0. Common
const element = Blaze.getData(evt.currentTarget); const element = Blaze.getData(evt.currentTarget);
element.boardId = this.boardId;
let _id = ''; let _id = '';
if (!this.isTemplateSearch || this.isCardTemplateSearch) { if (!this.isTemplateSearch || this.isCardTemplateSearch) {
// Card insertion // Card insertion
// 1. Common // 1. Common
element.boardId = this.boardId;
element.listId = this.listId; element.listId = this.listId;
element.swimlaneId = this.swimlaneId; element.swimlaneId = this.swimlaneId;
element.sort = Lists.findOne(this.listId).cards().count(); element.sort = Lists.findOne(this.listId).cards().count();
@ -620,7 +633,7 @@ BlazeComponent.extendComponent({
_id = element.copy(); _id = element.copy();
// 1.B Linked card // 1.B Linked card
} else { } else {
element._id = null; delete element._id;
element.type = 'cardType-linkedCard'; element.type = 'cardType-linkedCard';
element.linkedId = element.linkedId || element._id; element.linkedId = element.linkedId || element._id;
_id = Cards.insert(element); _id = Cards.insert(element);
@ -628,14 +641,22 @@ BlazeComponent.extendComponent({
Filter.addException(_id); Filter.addException(_id);
// List insertion // List insertion
} else if (this.isListTemplateSearch) { } else if (this.isListTemplateSearch) {
element.boardId = this.boardId;
element.sort = Swimlanes.findOne(this.swimlaneId).lists().count(); element.sort = Swimlanes.findOne(this.swimlaneId).lists().count();
element.type = 'list'; element.type = 'list';
element.swimlaneId = '';
_id = element.copy(this.swimlaneId); _id = element.copy(this.swimlaneId);
} else if (this.isSwimlaneTemplateSearch) { } else if (this.isSwimlaneTemplateSearch) {
element.boardId = this.boardId;
element.sort = Boards.findOne(this.boardId).swimlanes().count(); element.sort = Boards.findOne(this.boardId).swimlanes().count();
element.type = 'swimlalne'; element.type = 'swimlalne';
_id = element.copy(); _id = element.copy();
} else if (this.isBoardTemplateSearch) {
board = Boards.findOne(element.linkedId);
board.sort = Boards.find({archived: false}).count();
board.type = 'board';
delete board.slug;
delete board.members;
_id = board.copy();
} }
Popup.close(); Popup.close();
}, },

View file

@ -36,7 +36,10 @@ import sanitizeXss from 'xss';
const at = HTML.CharRef({html: '@', str: '@'}); const at = HTML.CharRef({html: '@', str: '@'});
Blaze.Template.registerHelper('mentions', new Template('mentions', function() { Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
const view = this; const view = this;
let content = Blaze.toHTML(view.templateContentBlock);
const currentBoard = Boards.findOne(Session.get('currentBoard')); const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (!currentBoard)
return HTML.Raw(sanitizeXss(content));
const knowedUsers = currentBoard.members.map((member) => { const knowedUsers = currentBoard.members.map((member) => {
const u = Users.findOne(member.userId); const u = Users.findOne(member.userId);
if(u){ if(u){
@ -45,7 +48,6 @@ Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
return member; return member;
}); });
const mentionRegex = /\B@([\w.]*)/gi; const mentionRegex = /\B@([\w.]*)/gi;
let content = Blaze.toHTML(view.templateContentBlock);
let currentMention; let currentMention;
while ((currentMention = mentionRegex.exec(content)) !== null) { while ((currentMention = mentionRegex.exec(content)) !== null) {

View file

@ -315,6 +315,21 @@ Boards.attachSchema(new SimpleSchema({
Boards.helpers({ Boards.helpers({
copy() {
const oldId = this._id;
delete this._id;
const _id = Boards.insert(this);
// Copy all swimlanes in board
Swimlanes.find({
boardId: oldId,
archived: false,
}).forEach((swimlane) => {
swimlane.type = 'swimlane';
swimlane.boardId = _id;
swimlane.copy(oldId);
});
},
/** /**
* Is supplied user authorized to view this board? * Is supplied user authorized to view this board?
*/ */
@ -463,6 +478,27 @@ Boards.helpers({
return _id; return _id;
}, },
searchBoards(term) {
check(term, Match.OneOf(String, null, undefined));
const query = { boardId: this._id };
query.type = 'cardType-linkedBoard';
query.archived = false;
const projection = { limit: 10, sort: { createdAt: -1 } };
if (term) {
const regex = new RegExp(term, 'i');
query.$or = [
{ title: regex },
{ description: regex },
];
}
return Cards.find(query, projection);
},
searchSwimlanes(term) { searchSwimlanes(term) {
check(term, Match.OneOf(String, null, undefined)); check(term, Match.OneOf(String, null, undefined));

View file

@ -69,7 +69,7 @@ CardComments.allow({
CardComments.helpers({ CardComments.helpers({
copy(newCardId) { copy(newCardId) {
this.cardId = newCardId; this.cardId = newCardId;
this._id = null; delete this._id;
CardComments.insert(this); CardComments.insert(this);
}, },

View file

@ -274,7 +274,7 @@ Cards.allow({
Cards.helpers({ Cards.helpers({
copy() { copy() {
const oldId = this._id; const oldId = this._id;
this._id = null; delete this._id;
const _id = Cards.insert(this); const _id = Cards.insert(this);
// copy checklists // copy checklists

View file

@ -139,20 +139,24 @@ Lists.allow({
Lists.helpers({ Lists.helpers({
copy(swimlaneId) { copy(swimlaneId) {
const oldId = this._id; const oldId = this._id;
const oldSwimlaneId = this.swimlaneId || null;
let _id = null; let _id = null;
existingListWithSameName = Lists.findOne({ existingListWithSameName = Lists.findOne({
boardId: this.boardId, boardId: this.boardId,
title: this.title, title: this.title,
archived: false,
}); });
if (existingListWithSameName) { if (existingListWithSameName) {
_id = existingListWithSameName._id; _id = existingListWithSameName._id;
} else { } else {
this._id = null; delete this._id;
delete this.swimlaneId;
_id = Lists.insert(this); _id = Lists.insert(this);
} }
// Copy all cards in list // Copy all cards in list
Cards.find({ Cards.find({
swimlaneId: oldSwimlaneId,
listId: oldId, listId: oldId,
archived: false, archived: false,
}).forEach((card) => { }).forEach((card) => {

View file

@ -101,18 +101,23 @@ Swimlanes.allow({
}); });
Swimlanes.helpers({ Swimlanes.helpers({
copy() { copy(oldBoardId) {
const oldId = this._id; const oldId = this._id;
this._id = null; delete this._id;
const _id = Swimlanes.insert(this); const _id = Swimlanes.insert(this);
// Copy all lists in swimlane const query = {
Lists.find({ swimlaneId: {$in: [oldId, '']},
swimlaneId: oldId,
archived: false, archived: false,
}).forEach((list) => { };
if (oldBoardId) {
query.boardId = oldBoardId;
}
// Copy all lists in swimlane
Lists.find(query).forEach((list) => {
list.type = 'list'; list.type = 'list';
list.swimlaneId = ''; list.swimlaneId = oldId;
list.boardId = this.boardId; list.boardId = this.boardId;
list.copy(_id); list.copy(_id);
}); });