| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 | import { ReactiveCache } from '/imports/reactiveCache';import { TAPi18n } from '/imports/i18n';import Cards from '/models/cards';import Boards from '/models/boards';import { DialogWithBoardSwimlaneListCard } from '/client/lib/dialogWithBoardSwimlaneListCard';const subManager = new SubsManager();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: true,    start(evt, ui) {      ui.placeholder.height(ui.helper.height());      EscapeActions.clickExecute(evt.target, 'inlinedForm');    },    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 ReactiveCache.getCurrentUser()?.isBoardMember();    }    // Disable sorting if the current user is not a board member    self.autorun(() => {      const $itemsDom = $(self.itemsDom);      if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) {        $(self.itemsDom).sortable('option', 'disabled', !userIsMember());        if (Utils.isTouchScreenOrShowDesktopDragHandles()) {          $(self.itemsDom).sortable({            handle: 'span.fa.checklistitem-handle',          });        }      }    });  },  /** returns the finished percent of the checklist */  finishedPercent() {    const ret = this.data().checklist.finishedPercent();    return ret;  },}).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 = ReactiveCache.getCard(cardId);    //if (card.isLinked()) cardId = card.linkedId;    if (card.isLinkedCard()) {      cardId = card.linkedId;    }    let sortIndex;    let checklistItemIndex;    if (this.currentData().position === 'top') {      sortIndex = Utils.calculateIndexData(null, card.firstChecklist()).base;      checklistItemIndex = 0;    } else {      sortIndex = Utils.calculateIndexData(card.lastChecklist(), null).base;      checklistItemIndex = -1;    }    if (title) {      Checklists.insert({        cardId,        title,        sort: sortIndex,      });      this.closeAllInlinedForms();      setTimeout(() => {        this.$('.add-checklist-item')          .eq(checklistItemIndex)          .click();      }, 100);    }  },  addChecklistItem(event) {    event.preventDefault();    const textarea = this.find('textarea.js-add-checklist-item');    const newlineBecomesNewChecklistItem = this.find('input#toggleNewlineBecomesNewChecklistItem');    const title = textarea.value.trim();    const checklist = this.currentData().checklist;    if (title) {      let checklistItems = [title];      if (newlineBecomesNewChecklistItem.checked) {        checklistItems = title.split('\n').map(_value => _value.trim());        if (this.currentData().position === 'top') {          checklistItems = checklistItems.reverse();        }      }      for (let checklistItem of checklistItems) {        let sortIndex;        if (this.currentData().position === 'top') {          sortIndex = Utils.calculateIndexData(null, checklist.firstItem()).base;        } else {          sortIndex = Utils.calculateIndexData(checklist.lastItem(), null).base;        }        ChecklistItems.insert({          title: checklistItem,          checklistId: checklist._id,          cardId: checklist.cardId,          sort: sortIndex,        });      }    }    // We keep the form opened, empty it.    textarea.value = '';    textarea.focus();  },  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);  },  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();    }  },  /** closes all inlined forms (checklist and checklist-item input fields) */  closeAllInlinedForms() {    this.$('.js-close-inlined-form').click();  },  events() {    const events = {    };    return [      {        ...events,        'click .js-open-checklist-details-menu': Popup.open('checklistActions'),        '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-convert-checklist-item-to-card': Popup.open('convertChecklistItemToCard'),        'click .js-delete-checklist-item': this.deleteItem,        'focus .js-add-checklist-item': this.focusChecklistItem,        // add and delete checklist / checklist-item        'click .js-open-inlined-form': this.closeAllInlinedForms,        keydown: this.pressKey,      },    ];  },}).register('checklists');BlazeComponent.extendComponent({  onCreated() {    subManager.subscribe('board', Session.get('currentBoard'), false);    this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));  },  boards() {    const ret = ReactiveCache.getBoards(      {        archived: false,        'members.userId': Meteor.userId(),        _id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },      },      {        sort: { sort: 1 /* boards default sorting */ },      },    );    return ret;  },  swimlanes() {    const board = ReactiveCache.getBoard(this.selectedBoardId.get());    return board.swimlanes();  },  aBoardLists() {    const board = ReactiveCache.getBoard(this.selectedBoardId.get());    return board.lists();  },  events() {    return [      {        'change .js-select-boards'(event) {          this.selectedBoardId.set($(event.currentTarget).val());          subManager.subscribe('board', this.selectedBoardId.get(), false);        },      },    ];  },}).register('boardsSwimlanesAndLists');Template.checklists.helpers({  checklists() {    const card = ReactiveCache.getCard(this.cardId);    const ret = card.checklists();    return ret;  },  showAtMinicard() {    const card = ReactiveCache.getCard(this.cardId);    const ret = card.checklists({'showAtMinicard':1});    return ret;  },  hideCheckedItems() {    const currentUser = ReactiveCache.getCurrentUser();    if (currentUser) return currentUser.hasHideCheckedItems();    return false;  },});BlazeComponent.extendComponent({  onRendered() {    autosize(this.$('textarea.js-add-checklist-item'));  },  events() {    return [      {        'click a.fa.fa-copy'(event) {          const $editor = this.$('textarea');          const promise = Utils.copyTextToClipboard($editor[0].value);          const $tooltip = this.$('.copied-tooltip');          Utils.showCopied(promise, $tooltip);        },      }    ];  }}).register('addChecklistItemForm');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,        'click #toggleShowChecklistAtMinicardButton'() {          const checklist = this.checklist;          if (checklist && checklist._id) {            Meteor.call('toggleShowChecklistAtMinicard', checklist._id);          }        },        'click #toggleHideCheckedItemsButton'() {          Meteor.call('toggleHideCheckedItems');        },        'click .js-delete-checklist': Popup.afterConfirm('checklistDelete', function () {          Popup.back(2);          const checklist = this.checklist;          if (checklist && checklist._id) {            Checklists.remove(checklist._id);          }        }),        'click .js-move-checklist': Popup.open('moveChecklist'),        'click .js-copy-checklist': Popup.open('copyChecklist'),      }    ]  }}).register('checklistActionsPopup');BlazeComponent.extendComponent({  onRendered() {    autosize(this.$('textarea.js-edit-checklist-item'));  },  events() {    return [      {        'click a.fa.fa-copy'(event) {          const $editor = this.$('textarea');          const promise = Utils.copyTextToClipboard($editor[0].value);          const $tooltip = this.$('.copied-tooltip');          Utils.showCopied(promise, $tooltip);        },      }    ];  }}).register('editChecklistItemForm');Template.checklistItemDetail.helpers({  hideCheckedItems() {    const user = ReactiveCache.getCurrentUser();    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');/** Move Checklist Dialog */(class extends DialogWithBoardSwimlaneListCard {  getDialogOptions() {    const ret = ReactiveCache.getCurrentUser().getMoveChecklistDialogOptions();    return ret;  }  setDone(cardId, options) {    ReactiveCache.getCurrentUser().setMoveChecklistDialogOption(this.currentBoardId, options);    this.data().checklist.move(cardId);  }}).register('moveChecklistPopup');/** Copy Checklist Dialog */(class extends DialogWithBoardSwimlaneListCard {  getDialogOptions() {    const ret = ReactiveCache.getCurrentUser().getCopyChecklistDialogOptions();    return ret;  }  setDone(cardId, options) {    ReactiveCache.getCurrentUser().setCopyChecklistDialogOption(this.currentBoardId, options);    this.data().checklist.copy(cardId);  }}).register('copyChecklistPopup');
 |