1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 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) 2005, 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 defines a search folder class. 27 */ 28 29 /** 30 * Creates the search folder. 31 * @class 32 * This class represents a search folder. 33 * 34 * @param {Hash} params a hash of parameters 35 * 36 * @extends ZmFolder 37 */ 38 ZmSearchFolder = function(params) { 39 params.type = ZmOrganizer.SEARCH; 40 ZmFolder.call(this, params); 41 42 if (params.query) { 43 var searchParams = { 44 query: params.query, 45 types: params.types, 46 checkTypes: true, 47 sortBy: params.sortBy, 48 searchId: params.id, 49 accountName: (params.account && params.account.name) 50 }; 51 this.search = new ZmSearch(searchParams); 52 } 53 }; 54 55 ZmSearchFolder.prototype = new ZmFolder; 56 ZmSearchFolder.prototype.constructor = ZmSearchFolder; 57 58 /** 59 * Returns a string representation of the object. 60 * 61 * @return {String} a string representation of the object 62 */ 63 ZmSearchFolder.prototype.toString = function() { 64 return "ZmSearchFolder"; 65 }; 66 67 ZmSearchFolder.ID_ROOT = ZmOrganizer.ID_ROOT; 68 69 /** 70 * Creates a search folder. 71 * 72 * @param {Hash} params a hash of parameters 73 */ 74 ZmSearchFolder.create = function(params) { 75 76 params = params || {}; 77 78 var search = params.search, 79 jsonObj = { CreateSearchFolderRequest: { _jsns:"urn:zimbraMail" } }, 80 searchNode = jsonObj.CreateSearchFolderRequest.search = {}; 81 82 searchNode.name = params.name; 83 searchNode.query = search.query; 84 searchNode.l = params.l; 85 if (params.sortBy) { 86 searchNode.sortBy = params.sortBy; 87 } 88 89 searchNode.types = ZmSearchFolder._getSearchTypes(search); 90 91 if (params.rgb) { 92 searchNode.rgb = params.rgb; 93 } 94 else if (params.color) { 95 var color = ZmOrganizer.getColorValue(params.color, params.type); 96 if (color) { 97 searchNode.color = color; 98 } 99 } 100 101 var accountName; 102 if (params.isGlobal) { 103 searchNode.f = 'g'; 104 accountName = appCtxt.accountList.mainAccount.name; 105 } 106 107 return appCtxt.getAppController().sendRequest({ 108 jsonObj: jsonObj, 109 asyncMode: params.asyncMode !== false, 110 accountName: accountName, 111 callback: ZmSearchFolder._handleCreate, 112 errorCallback: params.errorCallback || ZmOrganizer._handleErrorCreate.bind(null) 113 }); 114 }; 115 116 // converts a vector of types to a string the server can understand 117 ZmSearchFolder._getSearchTypes = function(search) { 118 119 var typeStr = ""; 120 if (search && search.types) { 121 var a = search.types.getArray(); 122 if (a.length) { 123 var typeStr = []; 124 for (var i = 0; i < a.length; i++) { 125 typeStr.push(ZmSearch.TYPE[a[i]]); 126 } 127 typeStr = typeStr.join(","); 128 } 129 } 130 return typeStr; 131 }; 132 133 ZmSearchFolder._handleCreate = 134 function(params) { 135 appCtxt.setStatusMsg(ZmMsg.searchSaved); 136 }; 137 138 /** 139 * Sets the underlying search query. 140 * 141 * @param {String} query search query 142 * @param {AjxCallback} callback the callback 143 * @param {AjxCallback} errorCallback the error callback 144 * @param {ZmBatchCommand} batchCmd the batch command 145 */ 146 ZmSearchFolder.prototype.setQuery = function(query, callback, errorCallback, batchCmd) { 147 148 if (query === this.search.query) { 149 return; 150 } 151 152 var params = { 153 callback: callback, 154 errorCallback: errorCallback, 155 batchCmd: batchCmd 156 }; 157 158 var cmd = "ModifySearchFolderRequest"; 159 var request = { 160 _jsns: "urn:zimbraMail", 161 search: { 162 query: query, 163 id: params.id || this.id, 164 types: ZmSearchFolder._getSearchTypes(this.search) 165 } 166 }; 167 var jsonObj = {}; 168 jsonObj[cmd] = request; 169 170 var respCallback = this._handleResponseOrganizerAction.bind(this, params); 171 if (params.batchCmd) { 172 params.batchCmd.addRequestParams(jsonObj, respCallback, params.errorCallback); 173 } 174 else { 175 var accountName; 176 if (appCtxt.multiAccounts) { 177 accountName = this.account ? this.account.name : appCtxt.accountList.mainAccount.name; 178 } 179 appCtxt.getAppController().sendRequest({ 180 jsonObj: jsonObj, 181 asyncMode: true, 182 accountName: accountName, 183 callback: respCallback, 184 errorCallback: params.errorCallback 185 }); 186 } 187 }; 188 189 /** 190 * Gets the icon. 191 * 192 * @return {String} the icon 193 */ 194 ZmSearchFolder.prototype.getIcon = 195 function() { 196 return (this.nId == ZmOrganizer.ID_ROOT) 197 ? null 198 : (this.isOfflineGlobalSearch ? "GlobalSearchFolder" : "SearchFolder"); 199 }; 200 201 /** 202 * Gets the tool tip. 203 * 204 */ 205 ZmSearchFolder.prototype.getToolTip = function() {}; 206 207 /** 208 * Returns the organizer with the given ID. Looks in this organizer's tree first. 209 * Since a search folder may have either a regular folder or another search folder 210 * as its parent, we may need to get the parent folder from another type of tree. 211 * 212 * @param {int} parentId the ID of the organizer to find 213 * 214 * @private 215 */ 216 ZmSearchFolder.prototype._getNewParent = 217 function(parentId) { 218 var parent = appCtxt.getById(parentId); 219 if (parent) { 220 return parent; 221 } 222 223 return appCtxt.getById(parentId); 224 }; 225 226 // Handle a change to the underlying search query 227 ZmSearchFolder.prototype.notifyModify = function(obj) { 228 229 if (obj.query && obj.query !== this.search.query && obj.id === this.id) { 230 this.search.query = obj.query; 231 var fields = {}; 232 fields[ZmOrganizer.F_QUERY] = true; 233 this._notify(ZmEvent.E_MODIFY, { 234 fields: fields 235 }); 236 obj.query = null; 237 } 238 ZmFolder.prototype.notifyModify.apply(this, [obj]); 239 }; 240