diff options
-rw-r--r-- | client/components/import/import.jade | 9 | ||||
-rw-r--r-- | client/components/import/import.js | 95 | ||||
-rw-r--r-- | models/import.js | 22 |
3 files changed, 84 insertions, 42 deletions
diff --git a/client/components/import/import.jade b/client/components/import/import.jade index 07e1116b..0f53e4d2 100644 --- a/client/components/import/import.jade +++ b/client/components/import/import.jade @@ -4,6 +4,11 @@ template(name="importPopup") form p: label(for='import-textarea') {{_ getLabel}} textarea#import-textarea.js-import-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus) + | {{jsonText}} + if membersMapping + div + a.show-mapping + | {{_ 'show-mapping'}} input.primary.wide(type="submit" value="{{_ 'import'}}") template(name="mapMembersPopup") @@ -24,7 +29,7 @@ template(name="mapMembersPopup") a.member.add-member.js-add-members i.fa.fa-plus form - input.primary.wide(type="submit" value="{{_ 'import'}}") + input.primary.wide(type="submit" value="{{_ 'done'}}") template(name="addMemberPopup") @@ -36,7 +41,7 @@ template(name="mapMembersAddPopup") ul.pop-over-list +esEach(index="users") li.item.js-member-item - a.name.js-select-member(title="{{profile.name}} ({{username}})" data-id="{{_id}}") + a.name.js-select-import(title="{{profile.name}} ({{username}})" data-id="{{_id}}") +userAvatar(userId=_id esSearch=true) span.full-name = profile.name diff --git a/client/components/import/import.js b/client/components/import/import.js index 3682afdb..b42fcc5d 100644 --- a/client/components/import/import.js +++ b/client/components/import/import.js @@ -11,6 +11,14 @@ const ImportPopup = BlazeComponent.extendComponent({ return 'importPopup'; }, + jsonText() { + return Session.get('import.text'); + }, + + membersMapping() { + return Session.get('import.membersToMap'); + }, + onCreated() { this.error = new ReactiveVar(''); this.dataToImport = ''; @@ -20,9 +28,21 @@ const ImportPopup = BlazeComponent.extendComponent({ Popup.close(); }, + onShowMapping(evt) { + // todo xxx make it work - currently we don't find the text + // this._storeText(evt); + Popup.open('mapMembers')(evt); + }, + + _storeText(evt) { + const dataJson = $(evt.currentTarget).find('.js-import-json').val(); + Session.set('import.text', dataJson); + return dataJson; + }, + onSubmit(evt){ evt.preventDefault(); - const dataJson = $(evt.currentTarget).find('.js-import-json').val(); + const dataJson = this._storeText(evt); let dataObject; try { dataObject = JSON.parse(dataJson); @@ -31,18 +51,14 @@ const ImportPopup = BlazeComponent.extendComponent({ this.setError('error-json-malformed'); return; } - // if there are members listed in the import, we need to map them - if(dataObject.members.length > 0) { + // if there are members listed in the import and we have no mapping for them... + if(dataObject.members.length > 0 && !this.membersMapping()) { // we will work on the list itself (an ordered array of POJO) // when a mapping is done, we add a 'wekan' field to the POJO representing the imported member const membersToMap = dataObject.members; - // todo save initial import object - to save later, on mapping submission - // this.data().toImport = dataObject; - // auto-map based on username - const wekanMembers = Users; membersToMap.forEach((importedMember) => { - const wekanUser = Users.findOne({username: importedMember.username}) + const wekanUser = Users.findOne({username: importedMember.username}); if(wekanUser) { importedMember.wekan = wekanUser; } @@ -52,7 +68,20 @@ const ImportPopup = BlazeComponent.extendComponent({ Session.set('import.membersToMap', membersToMap); Popup.open('mapMembers')(evt); } else { - Meteor.call(this.getMethodName(), dataObject, this.getAdditionalData(), + const additionalData = this.getAdditionalData(); + const membersMapping = this.membersMapping(); + if(membersMapping) { + const mappingById = {}; + membersMapping.forEach((member) => { + if (member.wekan) { + mappingById[member.id] = member.wekan._id; + } + }); + additionalData.membersMapping = mappingById; + } + Session.set('import.membersToMap', null); + Session.set('import.text', null); + Meteor.call(this.getMethodName(), dataObject, additionalData, (error, response) => { if (error) { this.setError(error.error); @@ -69,6 +98,7 @@ const ImportPopup = BlazeComponent.extendComponent({ events() { return [{ submit: this.onSubmit, + 'click .show-mapping': this.onShowMapping, }]; }, @@ -144,7 +174,7 @@ const ImportMapMembers = BlazeComponent.extendComponent({ listOfMembers.forEach((member) => { if(finder(member)) { if(value !== null) { - member[property] = true; + member[property] = value; } else { delete member[property]; } @@ -152,10 +182,8 @@ const ImportMapMembers = BlazeComponent.extendComponent({ // we shortcut if we don't care about unsetting the others return false; } - } else { - if(unset) { - delete member[property]; - } + } else if(unset) { + delete member[property]; } return true; }); @@ -188,47 +216,40 @@ const ImportMapMembers = BlazeComponent.extendComponent({ }); ImportMapMembers.extendComponent({ - onSelectMember(evt) { + onMapMember(evt) { const memberToMap = this.currentData(); - this.setSelectedMember(memberToMap.id); - console.log(`selected member#${memberToMap.id}`); - Popup.open('mapMembersAdd')(evt); - }, - onRemove(evt){ - const userId = this.currentData()._id; - console.log(`confirm and then call unmapMember ${userId}`); + if(memberToMap.wekan) { + // todo xxx ask for confirmation? + this.unmapMember(memberToMap.id); + } else { + this.setSelectedMember(memberToMap.id); + Popup.open('mapMembersAdd')(evt); + } }, onSubmit(evt) { - console.log("Mapping:"); - console.log(this.members()); + evt.preventDefault(); + Popup.back(); }, events() { return [{ 'submit': this.onSubmit, - 'click .js-add-members': this.onSelectMember, - 'click .js-member': this.onRemove, + 'click .mapping': this.onMapMember, }]; }, }).register('mapMembersPopup'); ImportMapMembers.extendComponent({ - //template() { - // return "mapMembersAddPopup"; - //}, onSelectUser(){ - const wekanUser = this.currentData(); - console.log(`clicked on ${wekanUser._id}`); - console.log(wekanUser); - //this.mapSelectedMember(this.currentData()); + this.mapSelectedMember(this.currentData()); + Popup.back(); }, events() { return [{ - //'click .js-select-member': this.onSelectUser(), + 'click .js-select-import': this.onSelectUser, }]; }, onRendered() { - console.log('rendered'); - // todo XXX why do I not focus?? - $('.js-map-member input').focus(); + // todo XXX why do I not get the focus?? + this.find('.js-map-member input').focus(); }, }).register('mapMembersAddPopup'); diff --git a/models/import.js b/models/import.js index a6e9f3d5..ab23f0a9 100644 --- a/models/import.js +++ b/models/import.js @@ -4,7 +4,7 @@ const DateString = Match.Where(function (dateAsString) { }); class TrelloCreator { - constructor() { + constructor(data) { // The object creation dates, indexed by Trello id (so we only parse actions // once!) this.createdAt = { @@ -18,6 +18,8 @@ class TrelloCreator { this.lists = {}; // The comments, indexed by Trello card id (to map when importing cards) this.comments = {}; + // the members, indexed by Trello member id => Wekan user ID + this.members = data.membersMapping ? data.membersMapping : {}; } checkActions(trelloActions) { @@ -191,6 +193,19 @@ class TrelloCreator { return this.labels[trelloId]; }); } + // add members { + if(card.idMembers) { + const wekanMembers = []; + // we can't just map, as some members may not have been mapped + card.idMembers.forEach((id) => { + if(this.members[id]) { + wekanMembers.push(this.members[id]); + } + }); + if(wekanMembers.length>0) { + cardToCreate.members = wekanMembers; + } + } // insert card const cardId = Cards.direct.insert(cardToCreate); // log activity @@ -298,7 +313,7 @@ class TrelloCreator { Meteor.methods({ importTrelloBoard(trelloBoard, data) { - const trelloCreator = new TrelloCreator(); + const trelloCreator = new TrelloCreator(data); // 1. check all parameters are ok from a syntax point of view try { @@ -326,13 +341,14 @@ Meteor.methods({ }, importTrelloCard(trelloCard, data) { - const trelloCreator = new TrelloCreator(); + const trelloCreator = new TrelloCreator(data); // 1. check parameters are ok from a syntax point of view try { check(data, { listId: String, sortIndex: Number, + membersMapping: Match.Optional(Object), }); trelloCreator.checkCards([trelloCard]); trelloCreator.checkLabels(trelloCard.labels); |