1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * Creates a left pane view for suggesting locations 26 * @constructor 27 * @class 28 * This class displays suggested free locations for a new appointment 29 * 30 * @author Vince Bellows 31 * 32 * @param newApptDialog [ZmApptQuickAddDialog] the new appt dialog 33 * @param container [DOM Element] the dialog's content Element 34 * @param controller [ZmApptComposeController] the appt compose controller 35 * @param closeCallback [Callback Function] Function to invoke upon close 36 */ 37 ZmLocationAssistantView = function(parent, controller, newApptDialog, closeCallback) { 38 ZmApptAssistantView.call(this, parent, controller, newApptDialog, closeCallback); 39 }; 40 41 ZmLocationAssistantView.prototype = new ZmApptAssistantView; 42 ZmLocationAssistantView.prototype.constructor = ZmLocationAssistantView; 43 44 45 ZmLocationAssistantView.prototype.toString = 46 function() { 47 return "ZmLocationAssistantView"; 48 } 49 50 ZmLocationAssistantView.prototype.cleanup = 51 function() { 52 if(this._locationSuggestions) this._locationSuggestions.removeAll(); 53 }; 54 55 56 ZmLocationAssistantView.prototype._configureSuggestionWidgets = 57 function() { 58 var locClassName = "DwtListView ZmSuggestLocationList"; 59 this._locationSuggestions = new ZmLocationSuggestionView(this, this._controller, 60 this._apptView, locClassName); 61 this._locationSuggestions.reparentHtmlElement(this._suggestionsView); 62 63 Dwt.setInnerHtml(this._suggestionName, ZmMsg.suggestedLocations); 64 65 this._suggestionsView.style.overflow = 'auto'; 66 Dwt.setVisible(this._suggestMinical, false); 67 }; 68 69 ZmLocationAssistantView.prototype.show = 70 function(containerSize) { 71 this._enabled = true; 72 if (!this._containerHeight) { 73 this._containerHeight = containerSize.y; 74 75 var nameSize = Dwt.getSize(this._suggestionName); 76 this._yAdjustment = nameSize.y + 20; 77 } 78 }; 79 80 ZmLocationAssistantView.prototype.suggestAction = 81 function(freeBusyCallback) { 82 83 if(appCtxt.isOffline && !appCtxt.isZDOnline()) { return; } 84 85 var params = { 86 items: [], 87 itemIndex: {}, 88 focus: true, 89 showOnlyGreenSuggestions: true, 90 fbCallback: freeBusyCallback 91 }; 92 93 this._locationSuggestions.setLoadingHtml(); 94 if(this._resources.length == 0) { 95 this.searchCalendarResources(new AjxCallback(this, this._findFreeBusyInfo, [params])); 96 } else { 97 this._findFreeBusyInfo(params); 98 } 99 }; 100 101 ZmLocationAssistantView.prototype._getTimeFrame = 102 function() { 103 var di = {}; 104 ZmApptViewHelper.getDateInfo(this._apptView, di); 105 var startDate = AjxDateUtil.simpleParseDateStr(di.startDate); 106 startDate.setHours(0, 0, 0, 0); 107 var endDate = AjxDateUtil.simpleParseDateStr(di.endDate); 108 endDate.setHours(23, 59, 59, 9999); 109 return {start:startDate, end:endDate}; 110 }; 111 112 ZmLocationAssistantView.prototype.updateTime = 113 function() { 114 var tf = this._getTimeFrame(); 115 this.reset(tf.start); 116 }; 117 118 ZmLocationAssistantView.prototype.reset = 119 function(date) { 120 var newDurationInfo = this._apptView.getDurationInfo(); 121 if(!this._duration || 122 ((newDurationInfo.startTime != this._duration.startTime) || 123 (newDurationInfo.endTime != this._duration.endTime))) { 124 this._duration = newDurationInfo; 125 if(this._locationSuggestions){ 126 this._locationSuggestions.removeAll(); 127 } 128 this.suggestAction(); 129 } 130 }; 131 132 ZmLocationAssistantView.prototype._findFreeBusyInfo = 133 function(params) { 134 135 var currAcct = this._apptView.getCalendarAccount(); 136 // Bug: 48189 Don't send GetFreeBusyRequest for non-ZCS accounts. 137 if (appCtxt.isOffline && (!currAcct.isZimbraAccount || currAcct.isMain)) { 138 //todo: avoid showing smart scheduler button for non-ZCS accounts - offline client 139 return; 140 } 141 142 var tf = this._getTimeFrame(); 143 144 params.itemIndex = {}; 145 params.items = []; 146 params.timeFrame = tf; 147 params.attendeeEmails = []; 148 149 var emails = []; 150 this._copyResourcesToParams(params, emails); 151 params.emails = emails; 152 153 if (this._freeBusyRequest) { 154 appCtxt.getRequestMgr().cancelRequest(this._freeBusyRequest, null, true); 155 } 156 157 var callback = params.fbCallback ? params.fbCallback : 158 new AjxCallback(this, this.suggestLocations, [params]); 159 var acct = (appCtxt.multiAccounts) ? this._apptView.getCalendarAccount() : null; 160 var fbParams = { 161 startTime: tf.start.getTime(), 162 endTime: tf.end.getTime(), 163 emails: emails, 164 callback: callback, 165 errorCallback: callback, 166 noBusyOverlay: true, 167 account: acct 168 }; 169 170 this._freeBusyRequest = this._fbCache.getFreeBusyInfo(fbParams); 171 }; 172 173 174 ZmLocationAssistantView.prototype.suggestLocations = 175 function(params) { 176 ZmApptAssistantView.prototype.suggestLocations.call(this, params); 177 Dwt.setSize(this._suggestionsView, Dwt.DEFAULT, this._containerHeight - this._yAdjustment); 178 }; 179 180 ZmLocationAssistantView.prototype.renderSuggestions = 181 function(params) { 182 params.list = params.locationInfo.locations; 183 params.totalLocations = this._totalLocations; 184 var warning = false; 185 if (params.list.size() >= ZmContactsApp.SEARCHFOR_MAX) { 186 // Problem: the locations search returned the Limit, implying there may 187 // be even more - and the location suggestion pane does not have a 'Next' 188 // button to get the next dollop, since large numbers of suggestions are 189 // not useful. Include a warning that the user should set their location prefs. 190 warning = true; 191 } 192 this._locationSuggestions.setWarning(warning); 193 194 this._locationSuggestions.set(params); 195 if(params.focus) this._locationSuggestions.focus(); 196 }; 197