import.js 6.0 KB

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