1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 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) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file defines the search tree controller. 27 * 28 */ 29 30 /** 31 * Creates a search tree controller. 32 * @class 33 * This class controls a tree display of saved searches. 34 * 35 * @author Conrad Damon 36 * 37 * @extends ZmFolderTreeController 38 */ 39 ZmSearchTreeController = function() { 40 41 ZmFolderTreeController.call(this, ZmOrganizer.SEARCH); 42 43 this._listeners[ZmOperation.RENAME_SEARCH] = this._renameListener.bind(this); 44 }; 45 46 ZmSearchTreeController.prototype = new ZmFolderTreeController; 47 ZmSearchTreeController.prototype.constructor = ZmSearchTreeController; 48 49 ZmSearchTreeController.prototype.isZmSearchTreeController = true; 50 ZmSearchTreeController.prototype.toString = function() { return "ZmSearchTreeController"; }; 51 52 ZmSearchTreeController.APP_JOIN_CHAR = "-"; 53 54 // Public methods 55 56 /** 57 * Shows the tree of this type. 58 * 59 * @param {Hash} params a hash of parameters 60 * @param {String} params.overviewId the overview ID 61 * @param {Boolean} params.showUnread if <code>true</code>, unread counts will be shown 62 * @param {Array} params.omit a hash of organizer IDs to ignore 63 * @param {Boolean} params.forceCreate if <code>true</code>, tree view will be created 64 * @param {ZmZimbraAccount} params.account the account to show tree for (if not currently active account) 65 * 66 */ 67 ZmSearchTreeController.prototype.show = 68 function(params) { 69 var id = params.overviewId; 70 if (!this._treeView[id] || params.forceCreate) { 71 this._treeView[id] = this._setup(id); 72 } 73 var dataTree = this.getDataTree(params.account); 74 if (dataTree) { 75 params.dataTree = dataTree; 76 params.searchTypes = {}; 77 params.omit = params.omit || {}; 78 params.omit[ZmFolder.ID_TRASH] = true; 79 params.omitParents = true; 80 var setting = ZmOrganizer.OPEN_SETTING[this.type]; 81 params.collapsed = !(!setting || (appCtxt.get(setting, null, params.account) !== false)); 82 var overview = this._opc.getOverview(id); 83 if (overview && overview.showNewButtons) 84 this._setupOptButton(params); 85 this._treeView[id].set(params); 86 this._checkTreeView(id); 87 } 88 89 return this._treeView[id]; 90 }; 91 92 /** 93 * Gets the tree style. 94 * 95 * @return {Object} the tree style or <code>null</code> if not set 96 */ 97 ZmSearchTreeController.prototype.getTreeStyle = 98 function() { 99 return null; 100 }; 101 102 /** 103 * Resets and enables/disables operations based on context. 104 * 105 * @param {ZmControl} parent the widget that contains the operations 106 * @param {constant} type the type 107 * @param {String} id the currently selected/activated organizer 108 */ 109 ZmSearchTreeController.prototype.resetOperations = 110 function(parent, type, id) { 111 parent.enableAll(true); 112 var search = appCtxt.getById(id); 113 parent.enable(ZmOperation.EXPAND_ALL, (search.size() > 0)); 114 }; 115 116 117 118 // Private methods 119 120 /** 121 * Returns ops available for "Searches" container. 122 * 123 * @private 124 */ 125 ZmSearchTreeController.prototype._getHeaderActionMenuOps = 126 function() { 127 return [ZmOperation.EXPAND_ALL]; 128 }; 129 130 /** 131 * Returns ops available for saved searches. 132 * 133 * @private 134 */ 135 ZmSearchTreeController.prototype._getActionMenuOps = 136 function() { 137 138 return [ 139 ZmOperation.MOVE, 140 ZmOperation.DELETE_WITHOUT_SHORTCUT, 141 ZmOperation.RENAME_SEARCH, 142 ZmOperation.EDIT_PROPS, 143 ZmOperation.OPEN_IN_TAB, 144 ZmOperation.EXPAND_ALL 145 ]; 146 }; 147 148 /** 149 * override the ZmFolderTreeController override. 150 * 151 * @private 152 */ 153 ZmSearchTreeController.prototype._getAllowedSubTypes = 154 function() { 155 return ZmTreeController.prototype._getAllowedSubTypes.call(this); 156 }; 157 158 /** 159 * Returns a "New Saved Search" dialog. 160 * 161 * @private 162 */ 163 ZmSearchTreeController.prototype._getNewDialog = 164 function() { 165 return appCtxt.getNewSearchDialog(); 166 }; 167 168 /** 169 * Called when a left click occurs (by the tree view listener). The saved 170 * search will be run. 171 * 172 * @param {ZmSearchFolder} searchFolder the search that was clicked 173 * 174 * @private 175 */ 176 ZmSearchTreeController.prototype._itemClicked = function(searchFolder, openInTab) { 177 178 if (searchFolder._showFoldersCallback) { 179 searchFolder._showFoldersCallback.run(); 180 return; 181 } 182 183 appCtxt.getSearchController().redoSearch(searchFolder.search, false, { 184 getHtml: appCtxt.get(ZmSetting.VIEW_AS_HTML), 185 userInitiated: openInTab, 186 origin: ZmId.SEARCH 187 }); 188 }; 189 190 // Miscellaneous 191 192 /** 193 * Returns a title for moving a saved search. 194 * 195 * @private 196 */ 197 ZmSearchTreeController.prototype._getMoveDialogTitle = 198 function() { 199 return AjxMessageFormat.format(ZmMsg.moveSearch, this._pendingActionData.name); 200 }; 201 202 /** 203 * Shows or hides the tree view. It is hidden only if there are no saved 204 * searches that belong to the owning app, and we have been told to hide empty 205 * tree views of this type. 206 * 207 * @param {constant} overviewId the overview ID 208 * 209 * @private 210 */ 211 ZmSearchTreeController.prototype._checkTreeView = 212 function(overviewId) { 213 var treeView = this._treeView[overviewId]; 214 if (!overviewId || !treeView) { return; } 215 216 var account = this._opc.getOverview(overviewId).account; 217 var rootId = (appCtxt.multiAccounts && !account.isMain) 218 ? (ZmOrganizer.getSystemId(ZmOrganizer.ID_ROOT, account)) 219 : ZmOrganizer.ID_ROOT; 220 var hide = ZmOrganizer.HIDE_EMPTY[this.type] && !treeView.getTreeItemById(rootId).getItemCount(); 221 this._treeView[overviewId].setVisible(!hide); 222 }; 223