1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file contains the task tree controller class. 27 */ 28 29 /** 30 * Creates the task tree controller. 31 * @class 32 * This class represents the task tree controller. 33 * 34 * @extends ZmFolderTreeController 35 */ 36 ZmTaskTreeController = function() { 37 38 ZmFolderTreeController.call(this, ZmOrganizer.TASKS); 39 40 this._listeners[ZmOperation.NEW_TASK_FOLDER] = new AjxListener(this, this._newListener); 41 this._listeners[ZmOperation.SHARE_TASKFOLDER] = new AjxListener(this, this._shareTaskFolderListener); 42 43 this._eventMgrs = {}; 44 }; 45 46 ZmTaskTreeController.prototype = new ZmFolderTreeController; 47 ZmTaskTreeController.prototype.constructor = ZmTaskTreeController; 48 49 /** 50 * Returns a string representation of the object. 51 * 52 * @return {String} a string representation of the object 53 */ 54 ZmTaskTreeController.prototype.toString = 55 function() { 56 return "ZmTaskTreeController"; 57 }; 58 59 // Public methods 60 61 /** 62 * Displays the tree of this type. 63 * 64 * @param {Hash} params a hash of parameters 65 * @param {constant} params.overviewId the overview ID 66 * @param {Boolean} params.showUnread if <code>true</code>, unread counts will be shown 67 * @param {Object} params.omit a hash of organizer IDs to ignore 68 * @param {Object} params.include a hash of organizer IDs to include 69 * @param {Boolean} params.forceCreate if <code>true</code>, tree view will be created 70 * @param {String} params.app the app that owns the overview 71 * @param {Boolean} params.hideEmpty if <code>true</code>, don't show header if there is no data 72 * @param {Boolean} params.noTooltips if <code>true</code>, don't show tooltips for tree items 73 */ 74 ZmTaskTreeController.prototype.show = function(params) { 75 params.include = params.include || {}; 76 params.include[ZmFolder.ID_TRASH] = true; 77 params.showUnread = false; 78 return ZmFolderTreeController.prototype.show.call(this, params); 79 }; 80 81 ZmTaskTreeController.prototype.resetOperations = 82 function(parent, type, id) { 83 var deleteText = ZmMsg.del; 84 var folder = appCtxt.getById(id); 85 var isShareVisible = true; 86 87 parent.enableAll(true); 88 if (folder) { 89 if (folder.isSystem() || appCtxt.isExternalAccount()) { 90 parent.enable([ZmOperation.DELETE_WITHOUT_SHORTCUT, ZmOperation.RENAME_FOLDER], false); 91 } else if (folder.link && !folder.isAdmin()) { 92 isShareVisible = false; 93 } 94 if (appCtxt.isOffline) { 95 var acct = folder.getAccount(); 96 isShareVisible = !acct.isMain && acct.isZimbraAccount; 97 } 98 parent.enable([ZmOperation.SHARE_TASKFOLDER], isShareVisible); 99 parent.enable(ZmOperation.SYNC, folder.isFeed()); 100 } 101 102 parent.enable(ZmOperation.EMPTY_FOLDER,((folder.numTotal > 0) || (folder.children && (folder.children.size() > 0)))); 103 var nId = ZmOrganizer.normalizeId(id); 104 var isTrash = nId == ZmOrganizer.ID_TRASH; 105 this.setVisibleIfExists(parent, ZmOperation.EMPTY_FOLDER, isTrash); 106 107 parent.enable(ZmOperation.EDIT_PROPS, !isTrash); 108 var emptyFolderOp = parent.getOp(ZmOperation.EMPTY_FOLDER); 109 if (emptyFolderOp) { 110 emptyFolderOp.setText(ZmMsg.emptyTrash); 111 } 112 113 this._enableRecoverDeleted(parent, isTrash); 114 115 var op = parent.getOp(ZmOperation.DELETE_WITHOUT_SHORTCUT); 116 if (op) { 117 op.setText(deleteText); 118 } 119 120 parent.enable(ZmOperation.NEW_TASK_FOLDER, !isTrash && !appCtxt.isExternalAccount()); 121 122 123 // we always enable sharing in case we're in multi-mbox mode 124 // But no sharing for trash folder 125 this._resetButtonPerSetting(parent, ZmOperation.SHARE_TASKFOLDER, !isTrash && appCtxt.get(ZmSetting.SHARING_ENABLED)); 126 }; 127 128 ZmTaskTreeController.prototype._getAllowedSubTypes = 129 function() { 130 return ZmTreeController.prototype._getAllowedSubTypes.call(this); 131 }; 132 133 ZmTaskTreeController.prototype._getSearchTypes = 134 function(ev) { 135 return [ZmItem.TASK]; 136 }; 137 /* 138 * Returns a "New Task Folder" dialog. 139 */ 140 ZmTaskTreeController.prototype._getNewDialog = 141 function() { 142 return appCtxt.getNewTaskFolderDialog(); 143 }; 144 145 ZmTaskTreeController.prototype._newCallback = 146 function(params) { 147 // For a task, set the parent folder (params.l) if specified 148 var folder = this._pendingActionData instanceof ZmOrganizer ? this._pendingActionData : 149 (this._pendingActionData && this._pendingActionData.organizer); 150 if (folder) { 151 params.l = folder.id; 152 } 153 ZmTreeController.prototype._newCallback.call(this, params); 154 }; 155 156 // Returns a list of desired header action menu operations 157 ZmTaskTreeController.prototype._getHeaderActionMenuOps = 158 function() { 159 if (appCtxt.isExternalAccount()) { 160 return []; 161 } 162 return [ZmOperation.NEW_TASK_FOLDER, ZmOperation.FIND_SHARES]; 163 }; 164 165 // Returns a list of desired action menu operations 166 ZmTaskTreeController.prototype._getActionMenuOps = function() { 167 168 return [ 169 ZmOperation.NEW_TASK_FOLDER, 170 ZmOperation.SYNC, 171 ZmOperation.EMPTY_FOLDER, 172 ZmOperation.RECOVER_DELETED_ITEMS, 173 ZmOperation.SHARE_TASKFOLDER, 174 ZmOperation.DELETE_WITHOUT_SHORTCUT, 175 ZmOperation.RENAME_FOLDER, 176 ZmOperation.EDIT_PROPS 177 ]; 178 }; 179 180 181 // Listeners 182 183 ZmTaskTreeController.prototype._shareTaskFolderListener = 184 function(ev) { 185 this._pendingActionData = this._getActionedOrganizer(ev); 186 appCtxt.getSharePropsDialog().popup(ZmSharePropsDialog.NEW, this._pendingActionData); 187 }; 188 189 ZmTaskTreeController.prototype._deleteListener = 190 function(ev) { 191 var organizer = this._getActionedOrganizer(ev); 192 if (organizer.isInTrash()) { 193 var callback = new AjxCallback(this, this._deleteListener2, [organizer]); 194 var message = AjxMessageFormat.format(ZmMsg.confirmDeleteTaskFolder, AjxStringUtil.htmlEncode(organizer.name)); 195 196 appCtxt.getConfirmationDialog().popup(message, callback); 197 } 198 else { 199 this._doMove(organizer, appCtxt.getById(ZmOrganizer.ID_TRASH)); 200 } 201 }; 202 203 ZmTaskTreeController.prototype._deleteListener2 = 204 function(organizer) { 205 this._doDelete(organizer); 206 }; 207 208 /** 209 * Called when a left click occurs (by the tree view listener). The folder that 210 * was clicked may be a search, since those can appear in the folder tree. The 211 * appropriate search will be performed. 212 * 213 * @param {ZmOrganizer} folder folder or search that was clicked 214 * 215 * @private 216 */ 217 ZmTaskTreeController.prototype._itemClicked = 218 function(folder) { 219 appCtxt.getApp(ZmApp.TASKS).search(folder); 220 }; 221 222 /** 223 * Gets the task Folders. 224 * 225 * @param {String} overviewId the overview id 226 * @param {boolean} includeTrash True to include trash, if checked. 227 * @return {Array} an array of {@link ZmCalendar} objects 228 */ 229 ZmTaskTreeController.prototype.getTaskFolders = 230 function(overviewId, includeTrash) { 231 var tasks = []; 232 var items = this._getItems(overviewId); 233 for (var i = 0; i < items.length; i++) { 234 var item = items[i]; 235 if (item._isSeparator) { continue; } 236 var task = item.getData(Dwt.KEY_OBJECT); 237 if (task && task.id == ZmOrganizer.ID_TRASH && !includeTrash && task.type) continue; 238 if (task) tasks.push(task); 239 } 240 241 return tasks; 242 }; 243 244 245 ZmTaskTreeController.prototype._getItems = 246 function(overviewId) { 247 var treeView = this.getTreeView(overviewId); 248 if (treeView) { 249 var account = appCtxt.multiAccounts ? treeView._overview.account : null; 250 if (!appCtxt.get(ZmSetting.TASKS_ENABLED, null, account)) { return []; } 251 252 var rootId = ZmOrganizer.getSystemId(ZmOrganizer.ID_ROOT, account); 253 var root = treeView.getTreeItemById(rootId); 254 if (root) { 255 var totalItems = []; 256 this._getSubItems(root, totalItems); 257 return totalItems; 258 } 259 } 260 return []; 261 }; 262 263 ZmTaskTreeController.prototype._getSubItems = 264 function(root, totalItems) { 265 if (!root || (root && root._isSeparator)) { return; } 266 267 var items = root.getItems(); 268 for (var i in items) { 269 var item = items[i]; 270 if (item && !item._isSeparator) { 271 totalItems.push(item); 272 this._getSubItems(item, totalItems); 273 } 274 } 275 }; 276