Browse Source

Import members: working on card import

Xavier Priour 9 năm trước cách đây
mục cha
commit
f6f41270de
3 tập tin đã thay đổi với 84 bổ sung42 xóa
  1. 7 2
      client/components/import/import.jade
  2. 58 37
      client/components/import/import.js
  3. 19 3
      models/import.js

+ 7 - 2
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

+ 58 - 37
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');

+ 19 - 3
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);