| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 | const { calculateIndexData, capitalize } = Utils;function initSorting(items) {  items.sortable({    tolerance: 'pointer',    helper: 'clone',    items: '.js-checklist-item:not(.placeholder)',    connectWith: '.js-checklist-items',    appendTo: 'parent',    distance: 7,    placeholder: 'checklist-item placeholder',    scroll: false,    start(evt, ui) {      ui.placeholder.height(ui.helper.height());      EscapeActions.executeUpTo('popup-close');    },    stop(evt, ui) {      const parent = ui.item.parents('.js-checklist-items');      const checklistId = Blaze.getData(parent.get(0)).checklist._id;      let prevItem = ui.item.prev('.js-checklist-item').get(0);      if (prevItem) {        prevItem = Blaze.getData(prevItem).item;      }      let nextItem = ui.item.next('.js-checklist-item').get(0);      if (nextItem) {        nextItem = Blaze.getData(nextItem).item;      }      const nItems = 1;      const sortIndex = calculateIndexData(prevItem, nextItem, nItems);      const checklistDomElement = ui.item.get(0);      const checklistData = Blaze.getData(checklistDomElement);      const checklistItem = checklistData.item;      items.sortable('cancel');      checklistItem.move(checklistId, sortIndex.base);    },  });}BlazeComponent.extendComponent({  onRendered() {    const self = this;    self.itemsDom = this.$('.js-checklist-items');    initSorting(self.itemsDom);    self.itemsDom.mousedown(function(evt) {      evt.stopPropagation();    });    function userIsMember() {      return Meteor.user() && Meteor.user().isBoardMember();    }    // Disable sorting if the current user is not a board member or is a miniscreen    self.autorun(() => {      const $itemsDom = $(self.itemsDom);      if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) {        $(self.itemsDom).sortable('option', 'disabled', !userIsMember());        if (Utils.isMiniScreenOrShowDesktopDragHandles()) {          $(self.itemsDom).sortable({            handle: 'span.fa.checklistitem-handle',          });        }      }    });  },  canModifyCard() {    return (      Meteor.user() &&      Meteor.user().isBoardMember() &&      !Meteor.user().isCommentOnly() &&      !Meteor.user().isWorker()    );  },}).register('checklistDetail');BlazeComponent.extendComponent({  addChecklist(event) {    event.preventDefault();    const textarea = this.find('textarea.js-add-checklist-item');    const title = textarea.value.trim();    let cardId = this.currentData().cardId;    const card = Cards.findOne(cardId);    if (card.isLinked()) cardId = card.linkedId;    if (title) {      Checklists.insert({        cardId,        title,        sort: card.checklists().count(),      });      setTimeout(() => {        this.$('.add-checklist-item')          .last()          .click();      }, 100);    }    textarea.value = '';    textarea.focus();  },  addChecklistItem(event) {    event.preventDefault();    const textarea = this.find('textarea.js-add-checklist-item');    const title = textarea.value.trim();    const checklist = this.currentData().checklist;    if (title) {      ChecklistItems.insert({        title,        checklistId: checklist._id,        cardId: checklist.cardId,        sort: checklist.itemCount(),      });    }    // We keep the form opened, empty it.    textarea.value = '';    textarea.focus();  },  canModifyCard() {    return (      Meteor.user() &&      Meteor.user().isBoardMember() &&      !Meteor.user().isCommentOnly() &&      !Meteor.user().isWorker()    );  },  deleteChecklist() {    const checklist = this.currentData().checklist;    if (checklist && checklist._id) {      Checklists.remove(checklist._id);      this.toggleDeleteDialog.set(false);    }  },  deleteItem() {    const checklist = this.currentData().checklist;    const item = this.currentData().item;    if (checklist && item && item._id) {      ChecklistItems.remove(item._id);    }  },  editChecklist(event) {    event.preventDefault();    const textarea = this.find('textarea.js-edit-checklist-item');    const title = textarea.value.trim();    const checklist = this.currentData().checklist;    checklist.setTitle(title);  },  editChecklistItem(event) {    event.preventDefault();    const textarea = this.find('textarea.js-edit-checklist-item');    const title = textarea.value.trim();    const item = this.currentData().item;    item.setTitle(title);  },  onCreated() {    this.toggleDeleteDialog = new ReactiveVar(false);    this.checklistToDelete = null; //Store data context to pass to checklistDeleteDialog 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();    }  },  focusChecklistItem(event) {    // If a new checklist is created, pre-fill the title and select it.    const checklist = this.currentData().checklist;    if (!checklist) {      const textarea = event.target;      textarea.value = capitalize(TAPi18n.__('r-checklist'));      textarea.select();    }  },  events() {    const events = {      'click .toggle-delete-checklist-dialog'(event) {        if ($(event.target).hasClass('js-delete-checklist')) {          this.checklistToDelete = this.currentData().checklist; //Store data context        }        this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get());      },      'click #toggleHideCheckedItemsButton'() {        Meteor.call('toggleHideCheckedItems');      },    };    return [      {        ...events,        'submit .js-add-checklist': this.addChecklist,        'submit .js-edit-checklist-title': this.editChecklist,        'submit .js-add-checklist-item': this.addChecklistItem,        'submit .js-edit-checklist-item': this.editChecklistItem,        'click .js-delete-checklist-item': this.deleteItem,        'click .confirm-checklist-delete': this.deleteChecklist,        'focus .js-add-checklist-item': this.focusChecklistItem,        keydown: this.pressKey,      },    ];  },}).register('checklists');Template.checklists.helpers({  hideCheckedItems() {    const currentUser = Meteor.user();    if (currentUser) return currentUser.hasHideCheckedItems();    return false;  },});Template.checklistDeleteDialog.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.checklistDeleteDialog.onDestroyed(() => {  const $cardDetails = this.$('.card-details');  $cardDetails.off('scroll'); //Reactivate scrolling  $cardDetails.animate({ scrollTop: this.scrollState.position });});Template.checklistItemDetail.helpers({  canModifyCard() {    return (      Meteor.user() &&      Meteor.user().isBoardMember() &&      !Meteor.user().isCommentOnly() &&      !Meteor.user().isWorker()    );  },  hideCheckedItems() {    const user = Meteor.user();    if (user) return user.hasHideCheckedItems();    return false;  },});BlazeComponent.extendComponent({  toggleItem() {    const checklist = this.currentData().checklist;    const item = this.currentData().item;    if (checklist && item && item._id) {      item.toggleItem();    }  },  events() {    return [      {        'click .js-checklist-item .check-box-container': this.toggleItem,      },    ];  },}).register('checklistItemDetail');
 |