import.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. BlazeComponent.extendComponent({
  2. onCreated() {
  3. this.error = new ReactiveVar('');
  4. this.steps = ['importTextarea', 'importMapMembers'];
  5. this._currentStepIndex = new ReactiveVar(0);
  6. this.importedData = new ReactiveVar();
  7. this.membersToMap = new ReactiveVar([]);
  8. },
  9. currentTemplate() {
  10. return this.steps[this._currentStepIndex.get()];
  11. },
  12. nextStep() {
  13. const nextStepIndex = this._currentStepIndex.get() + 1;
  14. if (nextStepIndex >= this.steps.length) {
  15. this.finishImport();
  16. } else {
  17. this._currentStepIndex.set(nextStepIndex);
  18. }
  19. },
  20. importData(evt) {
  21. evt.preventDefault();
  22. const dataJson = this.find('.js-import-json').value;
  23. try {
  24. const dataObject = JSON.parse(dataJson);
  25. this.setError('');
  26. this.importedData.set(dataObject);
  27. this._prepareAdditionalData(dataObject);
  28. this.nextStep();
  29. } catch (e) {
  30. this.setError('error-json-malformed');
  31. }
  32. },
  33. setError(error) {
  34. this.error.set(error);
  35. },
  36. finishImport() {
  37. const additionalData = {};
  38. const membersMapping = this.membersToMap.get();
  39. if (membersMapping) {
  40. const mappingById = {};
  41. membersMapping.forEach((member) => {
  42. if (member.wekanId) {
  43. mappingById[member.id] = member.wekanId;
  44. }
  45. });
  46. additionalData.membersMapping = mappingById;
  47. }
  48. this.membersToMap.set([]);
  49. Meteor.call('importTrelloBoard', this.importedData.get(), additionalData,
  50. (err, res) => {
  51. if (err) {
  52. this.setError(err.error);
  53. } else {
  54. Utils.goBoardId(res);
  55. }
  56. }
  57. );
  58. },
  59. _prepareAdditionalData(dataObject) {
  60. // we will work on the list itself (an ordered array of objects) when a
  61. // mapping is done, we add a 'wekan' field to the object representing the
  62. // imported member
  63. const membersToMap = dataObject.members;
  64. // auto-map based on username
  65. membersToMap.forEach((importedMember) => {
  66. const wekanUser = Users.findOne({ username: importedMember.username });
  67. if (wekanUser) {
  68. importedMember.wekanId = wekanUser._id;
  69. }
  70. });
  71. // store members data and mapping in Session
  72. // (we go deep and 2-way, so storing in data context is not a viable option)
  73. this.membersToMap.set(membersToMap);
  74. return membersToMap;
  75. },
  76. _screenAdditionalData() {
  77. return 'mapMembers';
  78. },
  79. }).register('import');
  80. BlazeComponent.extendComponent({
  81. template() {
  82. return 'importTextarea';
  83. },
  84. events() {
  85. return [{
  86. submit(evt) {
  87. return this.parentComponent().importData(evt);
  88. },
  89. }];
  90. },
  91. }).register('importTextarea');
  92. BlazeComponent.extendComponent({
  93. onCreated() {
  94. this.autorun(() => {
  95. this.parentComponent().membersToMap.get().forEach(({ wekanId }) => {
  96. if (wekanId) {
  97. this.subscribe('user-miniprofile', wekanId);
  98. }
  99. });
  100. });
  101. },
  102. members() {
  103. return this.parentComponent().membersToMap.get();
  104. },
  105. _refreshMembers(listOfMembers) {
  106. return this.parentComponent().membersToMap.set(listOfMembers);
  107. },
  108. /**
  109. * Will look into the list of members to import for the specified memberId,
  110. * then set its property to the supplied value.
  111. * If unset is true, it will remove the property from the rest of the list as well.
  112. *
  113. * use:
  114. * - memberId = null to use selected member
  115. * - value = null to unset a property
  116. * - unset = true to ensure property is only set on 1 member at a time
  117. */
  118. _setPropertyForMember(property, value, memberId, unset = false) {
  119. const listOfMembers = this.members();
  120. let finder = null;
  121. if(memberId) {
  122. finder = (member) => member.id === memberId;
  123. } else {
  124. finder = (member) => member.selected;
  125. }
  126. listOfMembers.forEach((member) => {
  127. if(finder(member)) {
  128. if(value !== null) {
  129. member[property] = value;
  130. } else {
  131. delete member[property];
  132. }
  133. if(!unset) {
  134. // we shortcut if we don't care about unsetting the others
  135. return false;
  136. }
  137. } else if(unset) {
  138. delete member[property];
  139. }
  140. return true;
  141. });
  142. // Session.get gives us a copy, we have to set it back so it sticks
  143. this._refreshMembers(listOfMembers);
  144. },
  145. setSelectedMember(memberId) {
  146. return this._setPropertyForMember('selected', true, memberId, true);
  147. },
  148. /**
  149. * returns the member with specified id,
  150. * or the selected member if memberId is not specified
  151. */
  152. getMember(memberId = null) {
  153. const allMembers = this.members();
  154. let finder = null;
  155. if (memberId) {
  156. finder = (user) => user.id === memberId;
  157. } else {
  158. finder = (user) => user.selected;
  159. }
  160. return allMembers.find(finder);
  161. },
  162. mapSelectedMember(wekanId) {
  163. return this._setPropertyForMember('wekanId', wekanId, null);
  164. },
  165. unmapMember(memberId){
  166. return this._setPropertyForMember('wekanId', null, memberId);
  167. },
  168. onSubmit(evt) {
  169. evt.preventDefault();
  170. this.parentComponent().nextStep();
  171. },
  172. onMapMember(evt) {
  173. const memberToMap = this.currentData();
  174. if(memberToMap.wekan) {
  175. // todo xxx ask for confirmation?
  176. this.unmapMember(memberToMap.id);
  177. } else {
  178. this.setSelectedMember(memberToMap.id);
  179. Popup.open('importMapMembersAdd')(evt);
  180. }
  181. },
  182. events() {
  183. return [{
  184. 'submit': this.onSubmit,
  185. 'click .js-select-member': this.onMapMember,
  186. }];
  187. },
  188. }).register('importMapMembers');
  189. BlazeComponent.extendComponent({
  190. onRendered() {
  191. this.find('.js-map-member input').focus();
  192. },
  193. onSelectUser(){
  194. Popup.getOpenerComponent().mapSelectedMember(this.currentData()._id);
  195. Popup.back();
  196. },
  197. events() {
  198. return [{
  199. 'click .js-select-import': this.onSelectUser,
  200. }];
  201. },
  202. }).register('importMapMembersAddPopup');