1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 ZmTaskMgr = function(container) { 25 this._container = container; 26 //this.clearCache(); 27 28 this._listeners = {}; 29 this._folderNames = {}; 30 31 }; 32 33 ZmTaskMgr.prototype = new ZmCalMgr; 34 ZmTaskMgr.prototype.constructor = ZmTaskMgr; 35 36 ZmTaskMgr.prototype.toString = 37 function() { 38 return "ZmTaskMgr"; 39 }; 40 41 ZmTaskMgr.prototype._refreshCallback = 42 function(list) { 43 this.getReminderController()._refreshCallback(list); 44 }; 45 46 ZmTaskMgr.prototype.getReminderController = 47 function() { 48 if (!this._reminderController) { 49 this._reminderController = new ZmReminderController(this, "task"); 50 } 51 return this._reminderController; 52 }; 53 54 ZmTaskMgr.prototype.getCalViewController = 55 function() { 56 var taskController = AjxDispatcher.run("GetTaskController"); 57 return taskController; 58 }; 59 60 ZmTaskMgr.prototype._miniCalMouseOutDayCallback = 61 function(control) { 62 this._currentMouseOverDay = null; 63 }; 64 65 ZmTaskMgr.prototype.getApptSummaries = 66 function(params) { 67 var apptVec = this.setSearchParams(params); 68 69 if (apptVec != null && (apptVec instanceof AjxVector)) { 70 return apptVec; 71 } 72 73 // this array will hold a list of tasks as we collect them from the server 74 this._rawTasks = []; 75 76 if (params.callback) { 77 this._search(params); 78 } else { 79 return this._search(params); 80 } 81 }; 82 83 ZmTaskMgr.prototype.setSearchParams = 84 function(params) { 85 if (!(params.folderIds instanceof Array)) { 86 params.folderIds = [params.folderIds]; 87 } else if (params.folderIds.length == 0) { 88 var newVec = new AjxVector(); 89 if (params.callback) { 90 params.callback.run(newVec); 91 } 92 return newVec; 93 } 94 95 var folderIdMapper = {}; 96 var query = ""; 97 for (var i=0; i < params.folderIds.length; i++) { 98 var fid = params.folderIds[i]; 99 var systemFolderId = appCtxt.getActiveAccount().isMain 100 ? fid : ZmOrganizer.getSystemId(fid); 101 102 // map remote folder ids into local ones while processing search since 103 // server wont do it for us (see bug 7083) 104 var folder = appCtxt.getById(systemFolderId); 105 var rid = folder ? folder.getRemoteId() : systemFolderId; 106 folderIdMapper[rid] = systemFolderId; 107 108 if (query.length) { 109 query += " OR "; 110 } 111 var idText = AjxUtil.isNumeric(fid) ? fid : ['"', fid, '"'].join(""); 112 query += "inid:" + idText; 113 114 } 115 params.queryHint = query; 116 params.folderIdMapper = folderIdMapper; 117 params.offset = 0; 118 }; 119 120 ZmTaskMgr.prototype._search = 121 function(params) { 122 var jsonObj = {SearchRequest:{_jsns:"urn:zimbraMail"}}; 123 var request = jsonObj.SearchRequest; 124 125 this._setSoapParams(request, params); 126 127 var accountName = appCtxt.multiAccounts ? appCtxt.accountList.mainAccount.name : null; 128 if (params.callback) { 129 appCtxt.getAppController().sendRequest({ 130 jsonObj: jsonObj, 131 asyncMode: true, 132 callback: (new AjxCallback(this, this._getApptSummariesResponse, [params])), 133 noBusyOverlay: params.noBusyOverlay, 134 accountName: accountName 135 }); 136 } else { 137 var response = appCtxt.getAppController().sendRequest({jsonObj: jsonObj, accountName: accountName}); 138 var result = new ZmCsfeResult(response, false); 139 return this._getApptSummariesResponse(params, result); 140 } 141 }; 142 143 ZmTaskMgr.prototype._setSoapParams = 144 function(request, params) { 145 request.sortBy = "none"; 146 request.limit = "500"; 147 //request.calExpandInstStart = params.start; 148 //request.calExpandInstEnd = params.end; 149 request.types = ZmSearch.TYPE[ZmItem.TASK]; 150 request.offset = params.offset; 151 152 var query = params.query; 153 if (params.queryHint) { 154 query = (query != null) 155 ? (query + " (" + params.queryHint + ")") 156 : params.queryHint; 157 } 158 request.query = {_content:query}; 159 }; 160 161 162 ZmTaskMgr.prototype._getApptSummariesResponse = 163 function(params, result) { 164 // TODO: mark both as needing refresh? 165 if (!result) { return; } 166 167 var callback = params.callback; 168 var resp; 169 try { 170 resp = result.getResponse(); 171 } catch (ex) { 172 if (callback) { 173 callback.run(new AjxVector()); 174 } 175 return; 176 } 177 178 var searchResp = resp.SearchResponse; 179 var newList = this.processSearchResponse(searchResp, params); 180 if (newList == null) { return; } 181 182 if (callback) { 183 callback.run(newList, params.query); 184 } else { 185 return newList; 186 } 187 }; 188 189 ZmTaskMgr.prototype.processSearchResponse = 190 function(searchResp, params) { 191 if(!searchResp) { return; } 192 193 if (searchResp && searchResp.task && searchResp.task.length) { 194 this._rawTasks = this._rawTasks != null 195 ? this._rawTasks.concat(searchResp.task) 196 : searchResp.task; 197 198 // if "more" flag set, keep requesting more appts 199 if (searchResp.more) { 200 var lastAppt = searchResp.task[searchResp.task.length-1]; 201 if (lastAppt) { 202 params.offset += 500; 203 this._search(params); 204 return; 205 } 206 } 207 } 208 209 var newList = new AjxVector(); 210 if (this._rawTasks && this._rawTasks.length) { 211 //this._list = new ZmList(ZmItem.TASK); 212 for (var i = 0; i < this._rawTasks.length; i++) { 213 DBG.println(AjxDebug.DBG2, "task[j]:" + this._rawTasks[i].name); 214 var taskNode = this._rawTasks[i]; 215 ////var instances = taskNode ? taskNode.inst : null; 216 ////if (instances) { 217 //var args = {list:this._list}; 218 // Pass null as the list - otherwise the list, created above and used nowhere else 219 // for viewing will be the one associated with teh 220 var args = {list:null}; 221 ////for (var j = 0; j < instances.length; j++) { 222 var task = ZmTask.createFromDom(taskNode, args, null); 223 DBG.println(AjxDebug.DBG2, "lite task :" + task); 224 if (task) newList.add(task); 225 ////} 226 ////} 227 228 // Accumulate this list to be processed by the reminderController callback 229 newList.add(task); 230 } 231 232 } 233 return newList; 234 }; 235 236 ZmTaskMgr.prototype.getCalendarName = 237 function(folderId) { 238 var app = appCtxt.getApp(ZmApp.TASKS); 239 return app.getTaskFolderName(folderId); 240 }; 241 242 243 ZmTaskMgr.prototype.getCheckedCalendarFolderIds = 244 function(localOnly) { 245 var app = appCtxt.getApp(ZmApp.TASKS); 246 return app.getTaskFolderIds(localOnly); 247 }; 248 249 ZmTaskMgr.prototype._handleError = 250 function(ex) { 251 if (ex.code == 'mail.INVITE_OUT_OF_DATE' || ex.code == 'mail.NO_SUCH_APPT') { 252 var msgDialog = appCtxt.getMsgDialog(); 253 msgDialog.setMessage(ZmMsg.apptOutOfDate, DwtMessageDialog.INFO_STYLE); 254 msgDialog.popup(); 255 return true; 256 } 257 return false; 258 }; 259 260 261 ZmTaskMgr.prototype.getQuickReminderSearchTimeRange = 262 function() { 263 var endOfDay = new Date(); 264 endOfDay.setHours(23,59,59,999); 265 266 var end = new Date(endOfDay.getTime()); 267 268 var start = endOfDay; 269 start.setHours(0,0,0, 0); 270 271 return { start: start.getTime(), end: end.getTime() }; 272 }; 273 274 ZmTaskMgr.prototype.showQuickReminder = 275 function() { 276 var params = this.getQuickReminderParams(); 277 this.getApptSummaries(params); 278 }; 279 280 ZmTaskMgr.prototype.getQuickReminderParams = 281 function() { 282 283 var timeRange = this.getQuickReminderSearchTimeRange(); 284 return { 285 start: timeRange.start, 286 end: timeRange.end, 287 fanoutAllDay: false, 288 folderIds: this.getCheckedCalendarFolderIds(true), 289 callback: (new AjxCallback(this, this._quickReminderCallback)), 290 includeReminders: true 291 }; 292 }; 293 294 ZmTaskMgr.prototype._quickReminderCallback = 295 function(list) { 296 var newList = new AjxVector(); 297 this._cacheMap = {}; 298 var size = list.size(); 299 300 var currentTime = (new Date()).getTime(); 301 302 for (var i = 0; i < size; i++) { 303 var appt = list.get(i); 304 var id = appt.id; 305 if (!this._cacheMap[id]) { 306 this._cacheMap[id] = appt; 307 if(appt.isAllDayEvent()) continue; 308 var diff = appt.getStartTime() - currentTime; 309 var isUpcomingEvent = (diff >= 0 && diff <= AjxDateUtil.MSEC_PER_HOUR) 310 if((currentTime >= appt.getStartTime() && currentTime <= appt.getEndTime()) || isUpcomingEvent) { 311 appt.isUpcomingEvent = isUpcomingEvent; 312 newList.add(appt); 313 } 314 } 315 } 316 317 var qDlg = this.getQuickReminderDialog(); 318 qDlg.initialize(newList); 319 qDlg.popup(); 320 }; 321 322 323 /** 324 * Gets the quick reminder dialog. 325 * 326 * @return {ZmQuickReminderDialog} the dialog 327 */ 328 ZmTaskMgr.prototype.getQuickReminderDialog = 329 function() { 330 if (this._reminderDialog == null) { 331 this._reminderDialog = new ZmQuickReminderDialog(appCtxt.getShell(), this, this._calController); 332 } 333 return this._reminderDialog; 334 }; 335