| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 | BlazeComponent.extendComponent({  canModifyCard() {    return (      Meteor.user() &&      Meteor.user().isBoardMember() &&      !Meteor.user().isCommentOnly()    );  },}).register('subtaskDetail');BlazeComponent.extendComponent({  addSubtask(event) {    event.preventDefault();    const textarea = this.find('textarea.js-add-subtask-item');    const title = textarea.value.trim();    const cardId = this.currentData().cardId;    const card = Cards.findOne(cardId);    const sortIndex = -1;    const crtBoard = Boards.findOne(card.boardId);    const targetBoard = crtBoard.getDefaultSubtasksBoard();    const listId = targetBoard.getDefaultSubtasksListId();    const swimlaneId = targetBoard.getDefaultSwimline()._id;    if (title) {      const _id = Cards.insert({        title,        parentId: cardId,        members: [],        labelIds: [],        customFields: [],        listId,        boardId: targetBoard._id,        sort: sortIndex,        swimlaneId,        type: 'cardType-card',      });      // In case the filter is active we need to add the newly inserted card in      // the list of exceptions -- cards that are not filtered. Otherwise the      // card will disappear instantly.      // See https://github.com/wekan/wekan/issues/80      Filter.addException(_id);      setTimeout(() => {        this.$('.add-subtask-item')          .last()          .click();      }, 100);    }    textarea.value = '';    textarea.focus();  },  canModifyCard() {    return (      Meteor.user() &&      Meteor.user().isBoardMember() &&      !Meteor.user().isCommentOnly()    );  },  deleteSubtask() {    const subtask = this.currentData().subtask;    if (subtask && subtask._id) {      subtask.archive();      this.toggleDeleteDialog.set(false);    }  },  editSubtask(event) {    event.preventDefault();    const textarea = this.find('textarea.js-edit-subtask-item');    const title = textarea.value.trim();    const subtask = this.currentData().subtask;    subtask.setTitle(title);  },  onCreated() {    this.toggleDeleteDialog = new ReactiveVar(false);    this.subtaskToDelete = null; //Store data context to pass to subtaskDeleteDialog template  },  pressKey(event) {    //If user press enter key inside a form, submit it    //Unless the user is also holding down the 'shift' key    if (event.keyCode === 13 && !event.shiftKey) {      event.preventDefault();      const $form = $(event.currentTarget).closest('form');      $form.find('button[type=submit]').click();    }  },  events() {    const events = {      'click .toggle-delete-subtask-dialog'(event) {        if ($(event.target).hasClass('js-delete-subtask')) {          this.subtaskToDelete = this.currentData().subtask; //Store data context        }        this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get());      },      'click .js-view-subtask'(event) {        if ($(event.target).hasClass('js-view-subtask')) {          const subtask = this.currentData().subtask;          const board = subtask.board();          FlowRouter.go('card', {            boardId: board._id,            slug: board.slug,            cardId: subtask._id,          });        }      },    };    return [      {        ...events,        'submit .js-add-subtask': this.addSubtask,        'submit .js-edit-subtask-title': this.editSubtask,        'click .confirm-subtask-delete': this.deleteSubtask,        keydown: this.pressKey,      },    ];  },}).register('subtasks');Template.subtaskDeleteDialog.onCreated(() => {  const $cardDetails = this.$('.card-details');  this.scrollState = {    position: $cardDetails.scrollTop(), //save current scroll position    top: false, //required for smooth scroll animation  };  //Callback's purpose is to only prevent scrolling after animation is complete  $cardDetails.animate({ scrollTop: 0 }, 500, () => {    this.scrollState.top = true;  });  //Prevent scrolling while dialog is open  $cardDetails.on('scroll', () => {    if (this.scrollState.top) {      //If it's already in position, keep it there. Otherwise let animation scroll      $cardDetails.scrollTop(0);    }  });});Template.subtaskDeleteDialog.onDestroyed(() => {  const $cardDetails = this.$('.card-details');  $cardDetails.off('scroll'); //Reactivate scrolling  $cardDetails.animate({ scrollTop: this.scrollState.position });});Template.subtaskItemDetail.helpers({  canModifyCard() {    return (      Meteor.user() &&      Meteor.user().isBoardMember() &&      !Meteor.user().isCommentOnly()    );  },});BlazeComponent.extendComponent({  // ...}).register('subtaskItemDetail');
 |