class CardCategoryView extends DragTargetView { constructor(element) { super(element); this.cardViews = { }; this.cards = { }; OnTime.workTimeManager.addEventListener("periodstarted", this.onStartedCountingWithCard.bind(this)); OnTime.workTimeManager.addEventListener("periodended", this.onStoppedCountingWithCard.bind(this)); } build(element) { this.expandBar = document.createElement("DIV"); this.expandBar.className = "expand-bar expanded"; this.expandBar.addEventListener("click", this.onExpandBarClicked.bind(this)); element.appendChild(this.expandBar); this.expandIcon = document.createElement("DIV"); this.expandIcon.className = "expand-icon"; this.expandBar.appendChild(this.expandIcon); this.iconLabel = document.createElement("INPUT"); this.iconLabel.className = "icon-label"; this.iconLabel.setAttribute("list", "category-icons"); this.iconLabel.maxLength = 2; this.iconLabel.readOnly = true; this.iconLabel.addEventListener("change", this.onFieldChanged.bind(this)); this.expandBar.appendChild(this.iconLabel); this.titleLabel = document.createElement("INPUT"); this.titleLabel.className = "title-label"; this.titleLabel.readOnly = true; this.titleLabel.addEventListener("change", this.onFieldChanged.bind(this)); this.expandBar.appendChild(this.titleLabel); this.categoryOptionsButton = document.createElement("BUTTON"); this.categoryOptionsButton.className = "options require_w__card_category"; UIKit.registerAction(this, this.categoryOptionsButton, "contextmenu:card-category-options"); this.expandBar.appendChild(this.categoryOptionsButton); this.cardsContainer = document.createElement("DIV"); this.cardsContainer.className = "cards-container"; element.appendChild(this.cardsContainer); this.addCardButton = document.createElement("DIV"); this.addCardButton.className = "add-card-button require_w__card"; this.addCardButton.addEventListener("click", this.onAddCardButtonClicked.bind(this)); this.addCardButton.style.display = "none"; this.cardsContainer.appendChild(this.addCardButton); this.addCardButtonImage = document.createElement("IMG"); this.addCardButtonImage.src = OnTime.getResourceUri("Images/Add.png"); this.addCardButton.appendChild(this.addCardButtonImage); this.dummyCardView = document.createElement("DIV"); this.dummyCardView.className = "dummy-card-view"; this.cardsContainer.insertBefore(this.dummyCardView, this.cardsContainer.lastChild); return element; } setCategoryData(categoryData) { this.categoryData = categoryData; this.iconLabel.value = this.categoryData.icon; this.titleLabel.value = this.categoryData.name; this.addCardButton.setAttribute("category-key", this.categoryData.category_key); this.addCardButton.style.display = ""; } addCard(card) { if (card.card_key in this.cardViews) { console.error("Trying to add a card that already exists!"); return; } var cardView = new CardView(); cardView.setCardData(card); cardView.categoryView = this; cardView.viewController = this.viewController; cardView.element.classList.add("appeared"); this.cardsContainer.insertBefore(cardView.element, this.cardsContainer.lastChild); this.cardViews[card.card_key] = cardView; this.cards[card.card_key] = card; } removeCard(card) { if (!(card.card_key in this.cardViews)) { console.error("Trying to remove a card view that is not in the category!"); return; } this.cardsContainer.removeChild(this.cardViews[card.card_key].element); delete this.cardViews[card.card_key]; delete this.cards[card.card_key]; } changeCard(card) { this.cards[card.card_key] = card; this.cardViews[card.card_key].setCardData(card); } /** * Looks for the card view to transfer and disables it. * Returns the card view. */ prepareCardForTransfer(cardKey) { if (!(cardKey in this.cardViews)) { console.error("Trying to transfer the card without it being in the source view."); return; } var cardView = this.cardViews[cardKey]; cardView.element.classList.remove("appeared"); cardView.disableForTransfer(); return cardView; } /** * Called on the source view of a card drag. */ removeCardAfterTransfer(cardKey) { //Just use the standard function with a fake card. It does the same thing at the moment. this.removeCard({ card_key: cardKey }); } /** * Called on the target view of a card drag. */ receiveCardTransfer(cardView) { if (cardView.cardData.card_key in this.cardViews) { console.error("Trying to receive a card after transfer that already exists in the target category."); return; } this.cardsContainer.insertBefore(cardView.element, this.cardsContainer.lastChild); this.cardViews[cardView.cardData.card_key] = cardView; this.cards[cardView.cardData.card_key] = cardView.cardData; } showSourceDummy(insertionBeforeElement) { this.draggingElement = insertionBeforeElement; this.cardsContainer.insertBefore(this.dummyCardView, insertionBeforeElement); this.dummyCardView.classList.add("source"); } showTargetDummy() { this.cardsContainer.insertBefore(this.dummyCardView, this.cardsContainer.lastChild); this.dummyCardView.classList.add("target"); } hideDummy() { this.draggingElement = null; this.dummyCardView.classList.remove("source"); this.dummyCardView.classList.remove("target"); } acceptsType(draggableType) { //Refuse the card if the user has no write permission on the cards. return (draggableType == "card") && ("card" in OnTime.userManager.permissions) && OnTime.userManager.permissions.card == "w"; } setFilter(filterOptions) { for (var cardKey in this.cards) { var card = this.cards[cardKey]; var match = true; if (filterOptions.project_key && card.project_key != filterOptions.project_key) { match = false; } this.cardViews[cardKey].element.classList.remove("appeared"); if (!match) { if (this.cardViews[cardKey].element.className.indexOf("hidden-by-filter") == -1) { this.cardViews[cardKey].element.classList.add("hidden-by-filter"); } } else { this.cardViews[cardKey].element.classList.remove("hidden-by-filter"); } } } onDragEnter(draggedObject, validType, sourceView) { //Show the target dummy if this view is not the source. if (sourceView != this) { this.element.classList.add("dragging-over"); this.showTargetDummy(); } } onDragExit(sourceView) { this.element.classList.remove("dragging-over"); //Hide the target dummy if this view is not the source. if (sourceView != this) { this.hideDummy(); } } onDragEnd() { this.element.classList.remove("dragging-over"); } onDrop(droppedObject, sourceView) { //No cross-collection transfers allowed! if (sourceView.collectionView != this.collectionView || sourceView == this) { return; } OnTime.cardManager.transferCard(droppedObject.card_key, sourceView.categoryData.category_key, this.categoryData.category_key); } onExpandBarClicked(event) { if (event.target.nodeName != "button") { this.expandBar.classList.toggle("expanded"); } } onAddCardButtonClicked(event) { var categoryKey = event.currentTarget.getAttribute("category-key"); if (!categoryKey) { return; } var addCardViewController = UIKit.getViewControllerById("add-card-view-controller"); addCardViewController.setCategory(categoryKey); addCardViewController.cardCollectionView = this.collectionView; this.viewController.presentModalViewController(addCardViewController); } onStartedCountingWithCard(event) { if (event.period.card_key in this.cardViews) { this.cardViews[event.period.card_key].element.classList.add("counting"); } } onStoppedCountingWithCard(event) { if (event.period.card_key in this.cardViews) { this.cardViews[event.period.card_key].element.classList.remove("counting"); } } onRenameCategoryMenuItemPressed(event) { this.iconLabel.readOnly = false; this.titleLabel.readOnly = false; this.titleLabel.focus(); } onDeleteCategoryMenuItemPressed(event) { var deleteCategoryViewController = UIKit.getViewControllerById("delete-category-view-controller"); deleteCategoryViewController.setCategory(this.categoryData); this.viewController.presentModalViewController(deleteCategoryViewController); } /** * Called when the title or icon field is blurred. */ onFieldChanged(event) { if (this.validateChangedValues()) { this.saveValues(); this.iconLabel.readOnly = true; this.titleLabel.readOnly = true; } } /** * Validates the values from the input fields and returns true if they are valid and false otherwise. */ validateChangedValues() { if (this.iconLabel.value.length == 0 || this.iconLabel.value.length > 2) { return false; } if (this.titleLabel.value.length == 0) { return false; } return true; } /** * Sends the entered values in the input fields to the server. */ saveValues() { OnTime.cardManager.updateCategory({ category_key: this.categoryData.category_key, name: this.titleLabel.value, icon: this.iconLabel.value }); } onCategoryChanged(event) { if (event.category.category_key == this.categoryData.category_key) { this.setCategoryData(event.category); } } }