1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 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) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file contains the briefcase tree controller class. 27 * 28 */ 29 30 /** 31 * Creates the briefcase tree controller. 32 * @class 33 * This class is a controller for the tree view used by the briefcase application. 34 * 35 * @param {constant} type the organizer (see {@link ZmOrganizer.BRIEFCASE}) 36 * 37 * @author Parag Shah 38 * 39 * @extends ZmFolderTreeController 40 */ 41 ZmBriefcaseTreeController = function(type) { 42 43 ZmFolderTreeController.call(this, (type || ZmOrganizer.BRIEFCASE)); 44 45 this._listeners[ZmOperation.NEW_BRIEFCASE] = new AjxListener(this, this._newListener); 46 this._listeners[ZmOperation.SHARE_BRIEFCASE] = new AjxListener(this, this._shareBriefcaseListener); 47 48 this._eventMgrs = {}; 49 this._app = appCtxt.getApp(ZmApp.BRIEFCASE); 50 }; 51 52 ZmBriefcaseTreeController.prototype = new ZmFolderTreeController; 53 ZmBriefcaseTreeController.prototype.constructor = ZmBriefcaseTreeController; 54 55 /** 56 * Returns a string representation of the object. 57 * 58 * @return {String} a string representation of the object 59 */ 60 ZmBriefcaseTreeController.prototype.toString = 61 function() { 62 return "ZmBriefcaseTreeController"; 63 }; 64 65 // Public methods 66 67 ZmBriefcaseTreeController.prototype.resetOperations = 68 function(actionMenu, type, id) { 69 70 var rootId = ZmOrganizer.getSystemId(ZmOrganizer.ID_ROOT); 71 if (actionMenu && id != rootId) { 72 var briefcase = appCtxt.getById(id); 73 if (!briefcase) { return; } 74 var nId = ZmOrganizer.normalizeId(id); 75 var isRoot = (nId == rootId); 76 var isBriefcase = (nId == ZmOrganizer.getSystemId(ZmOrganizer.ID_BRIEFCASE)); 77 var isTopLevel = (!isRoot && briefcase.parent.id == rootId); 78 var isLink = briefcase.link; 79 var isLinkOrRemote = isLink || briefcase.isRemote(); 80 var isTrash = (nId == ZmFolder.ID_TRASH); 81 var isReadOnly = briefcase ? briefcase.isReadOnly() : false; 82 83 var deleteText = ZmMsg.del; 84 85 actionMenu.getOp(ZmOperation.EMPTY_FOLDER).setVisible(isTrash); 86 87 if (isTrash) { 88 var hasContent = ((briefcase.numTotal > 0) || (briefcase.children && (briefcase.children.size() > 0))); 89 actionMenu.enableAll(false); 90 actionMenu.enable(ZmOperation.EMPTY_FOLDER,hasContent); 91 actionMenu.getOp(ZmOperation.EMPTY_FOLDER).setText(ZmMsg.emptyTrash); 92 } else { 93 actionMenu.enableAll(true); 94 var showEditMenu = (!isLinkOrRemote || !isReadOnly || (isLink && isTopLevel) || ZmBriefcaseTreeController.__isAllowed(briefcase.parent, ZmShare.PERM_DELETE)); 95 actionMenu.enable(ZmOperation.DELETE_WITHOUT_SHORTCUT, showEditMenu && !isBriefcase); 96 actionMenu.enable(ZmOperation.EDIT_PROPS, showEditMenu); 97 98 var menuItem; 99 menuItem = actionMenu.getMenuItem(ZmOperation.NEW_BRIEFCASE); 100 menuItem.setText(ZmMsg.newFolder); 101 menuItem.setImage("NewFolder"); 102 menuItem.setEnabled((!isLinkOrRemote || ZmBriefcaseTreeController.__isAllowed(briefcase, ZmShare.PERM_CREATE_SUBDIR) || briefcase.isAdmin() || ZmShare.getRoleFromPerm(briefcase.perm) == ZmShare.ROLE_MANAGER)); 103 104 if (appCtxt.get(ZmSetting.SHARING_ENABLED)) { 105 isBriefcase = (!isRoot && briefcase.parent.id == rootId) || type==ZmOrganizer.BRIEFCASE; 106 menuItem = actionMenu.getMenuItem(ZmOperation.SHARE_BRIEFCASE); 107 menuItem.setText(ZmMsg.shareFolder); 108 menuItem.setImage(isBriefcase ? "SharedMailFolder" : "Section"); 109 var isShareVisible = (!isLinkOrRemote || briefcase.isAdmin()); 110 if (appCtxt.isOffline) { 111 var acct = briefcase.getAccount(); 112 isShareVisible = !acct.isMain && acct.isZimbraAccount; 113 } 114 menuItem.setEnabled(isShareVisible); 115 } 116 } 117 var op = actionMenu.getOp(ZmOperation.DELETE_WITHOUT_SHORTCUT); 118 if (op) { 119 op.setText(deleteText); 120 } 121 this._enableRecoverDeleted(actionMenu, isTrash); 122 123 // we always enable sharing in case we're in multi-mbox mode 124 this._resetButtonPerSetting(actionMenu, ZmOperation.SHARE_BRIEFCASE, appCtxt.get(ZmSetting.SHARING_ENABLED)); 125 126 } 127 128 }; 129 130 ZmBriefcaseTreeController.prototype._getAllowedSubTypes = 131 function() { 132 return ZmTreeController.prototype._getAllowedSubTypes.call(this); 133 }; 134 135 ZmBriefcaseTreeController.prototype._getSearchTypes = 136 function(ev) { 137 return [ZmItem.BRIEFCASE_ITEM]; 138 }; 139 140 ZmBriefcaseTreeController.__isAllowed = 141 function(organizer, perm) { 142 var allowed = true; 143 if (organizer.link || organizer.isRemote()) { 144 allowed = false; // change assumption to not allowed 145 146 // REVISIT: bug 10801 147 var share = organizer.getMainShare(); 148 if (share && !share.isPermRestricted(perm)) { 149 allowed = share.isPermAllowed(perm); 150 } 151 } 152 return allowed; 153 }; 154 155 // Returns a list of desired header action menu operations 156 ZmBriefcaseTreeController.prototype._getHeaderActionMenuOps = 157 function() { 158 var ops = []; 159 if (!appCtxt.isExternalAccount()) { 160 ops.push(ZmOperation.NEW_BRIEFCASE); 161 } 162 ops.push(ZmOperation.EXPAND_ALL); 163 if (!appCtxt.isExternalAccount()) { 164 ops.push(ZmOperation.FIND_SHARES); 165 } 166 return ops; 167 }; 168 169 // Returns a list of desired action menu operations 170 ZmBriefcaseTreeController.prototype._getActionMenuOps = 171 function() { 172 173 var ops = [ 174 ZmOperation.NEW_BRIEFCASE, 175 ZmOperation.EMPTY_FOLDER, 176 ZmOperation.RECOVER_DELETED_ITEMS 177 ]; 178 if (appCtxt.get(ZmSetting.SHARING_ENABLED)) { 179 ops.push(ZmOperation.SHARE_BRIEFCASE); 180 } 181 ops.push( 182 ZmOperation.DELETE_WITHOUT_SHORTCUT, 183 ZmOperation.EDIT_PROPS 184 ); 185 return ops; 186 }; 187 188 ZmBriefcaseTreeController.prototype._getNewDialog = 189 function() { 190 return appCtxt.getNewBriefcaseDialog(); 191 }; 192 193 /** 194 * Gets the tree style. 195 * 196 * @return {constant} the style 197 * 198 * @see DwtTree.SINGLE_STYLE 199 */ 200 ZmBriefcaseTreeController.prototype.getTreeStyle = 201 function() { 202 return DwtTree.SINGLE_STYLE; 203 }; 204 205 // Method that is run when a tree item is left-clicked 206 ZmBriefcaseTreeController.prototype._itemClicked = 207 function(folder) { 208 appCtxt.getApp(ZmApp.BRIEFCASE).search({ 209 folderId:folder.id, 210 callback: new AjxCallback(this, this._handleSearchResponse, [folder]) 211 }); 212 }; 213 214 // Listener callbacks 215 216 ZmBriefcaseTreeController.prototype._shareBriefcaseListener = 217 function(ev) { 218 this._pendingActionData = this._getActionedOrganizer(ev); 219 220 var briefcase = this._pendingActionData; 221 var share = null; 222 223 var sharePropsDialog = appCtxt.getSharePropsDialog(); 224 sharePropsDialog.popup(ZmSharePropsDialog.NEW, briefcase, share); 225 }; 226 227 ZmBriefcaseTreeController.prototype._notifyListeners = 228 function(overviewId, type, items, detail, srcEv, destEv) { 229 if (this._eventMgrs[overviewId] && this._eventMgrs[overviewId].isListenerRegistered(type)) { 230 if (srcEv) DwtUiEvent.copy(destEv, srcEv); 231 destEv.items = items; 232 if (items.length == 1) destEv.item = items[0]; 233 destEv.detail = detail; 234 this._eventMgrs[overviewId].notifyListeners(type, destEv); 235 } 236 }; 237 238 ZmBriefcaseTreeController.prototype._doCreate = 239 function(params) { 240 ZmTreeController.prototype._doCreate.apply(this, [params]); 241 }; 242 243 ZmBriefcaseTreeController.prototype._getItems = 244 function(overviewId) { 245 var treeView = this.getTreeView(overviewId); 246 if (treeView) { 247 var rootId = ZmOrganizer.getSystemId(ZmOrganizer.ID_ROOT); 248 var root = treeView.getTreeItemById(rootId); 249 if (root) { 250 return root.getItems(); 251 } 252 } 253 return []; 254 }; 255 256 ZmBriefcaseTreeController.prototype.show = 257 function(params) { 258 params.include = {}; 259 params.include[ZmFolder.ID_TRASH] = true; 260 params.showUnread = false; 261 var treeView = ZmFolderTreeController.prototype.show.call(this, params); 262 263 treeView._controller = this; 264 // Finder to BriefcaseTreeView drag and drop 265 this._initDragAndDrop(treeView); 266 267 return treeView; 268 }; 269 270 271 /** 272 * @private 273 */ 274 ZmBriefcaseTreeController.prototype._createTreeView = function(params) { 275 return new ZmBriefcaseTreeView(params); 276 }; 277 278 279 ZmBriefcaseTreeController.prototype._handleSearchResponse = 280 function(folder, result) { 281 // bug fix #49568 - Trash is special when in Briefcase app since it 282 // is a FOLDER type in BRIEFCASE tree. So reset selection if clicked 283 if (folder.nId == ZmFolder.ID_TRASH) { 284 this._treeView[this._app.getOverviewId()].setSelected(folder, true); 285 } 286 }; 287 288 289 ZmBriefcaseTreeController.prototype._initDragAndDrop = function(treeView) { 290 this._dnd = new ZmDragAndDrop(treeView); 291 }; 292