1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * Dialog containing the ZmResolveLocationView list. 26 * @constructor 27 * @class 28 * 29 * @author Vince Bellows 30 * 31 * @param controller [ZmApptComposeController] the appt compose controller 32 * @param composeView [ZmApptEditView] the appt edit view 33 * @param okCallback [function] callback upon OK 34 * @param assistantView [ZmScheduleAssistantView] Assistant that provides location FB info 35 * 36 */ 37 38 ZmResolveLocationConflictDialog = function(controller, composeView, okCallback, assistantView) { 39 this._controller = controller; 40 this._composeView = composeView; 41 42 this._okCallback = okCallback; 43 // The location assistant view associated with the parent appt view will 44 // provide the set of viable locations for each conflict date 45 this._assistantView = assistantView; 46 47 DwtDialog.call(this, {parent:appCtxt.getShell(), 48 title:ZmMsg.resolveLocationConflicts}); 49 50 this.setButtonListener(DwtDialog.OK_BUTTON, new AjxListener(this, this._handleOkButton)); 51 this.setButtonListener(DwtDialog.CANCEL_BUTTON, new AjxListener(this, this._handleCancelButton)); 52 }; 53 54 ZmResolveLocationConflictDialog.prototype = new DwtDialog; 55 ZmResolveLocationConflictDialog.prototype.constructor = ZmResolveLocationConflictDialog; 56 57 58 ZmResolveLocationConflictDialog.prototype.toString = 59 function() { 60 return "ZmResolveLocationConflictDialog"; 61 }; 62 63 // For each conflict dateTime, find the set of available locations. These will be used to 64 // populate the alternate location pulldowns 65 ZmResolveLocationConflictDialog.prototype._determineAlternateLocations = 66 function(params) { 67 var addr; 68 var durationInfo; 69 var locInfo; 70 var resolveLocInfo; 71 72 this._resolveLocList = new AjxVector(); 73 74 for (var i = 0; i < this._inst.length; i++) { 75 if (this._inst[i].usr) { 76 // A Conflict exists - add an entry to the resolution list 77 resolveLocInfo = {}; 78 resolveLocInfo.originalLocation = ZmResolveLocationView.NO_SELECTION; 79 resolveLocInfo.enabled = true; 80 var exceptionLoc = this._locationExceptions[this._inst[i].s]; 81 if (exceptionLoc) { 82 // Stored value (from either an existing exception in the DB or a 83 // previous use of this dialog). Save it to use for indicating the 84 // selected location in the alternate locations pulldown. 85 var locationEmails = []; 86 for (var j = 0; j < exceptionLoc.length; j++) { 87 locationEmails.push(exceptionLoc[j].getEmail()); 88 } 89 if (locationEmails.length > 1) { 90 // Multi select not currently supported. If an exception was created 91 // outside this dialog specifying multiple locations, just display it 92 // (i.e. do not create a pulldown, just create a label) 93 resolveLocInfo.originalLocation = locationEmails.join(','); 94 resolveLocInfo.enabled = false; 95 } else if (locationEmails.length == 1) { 96 resolveLocInfo.originalLocation = locationEmails[0]; 97 } 98 } 99 100 durationInfo = {}; 101 durationInfo.startTime = this._inst[i].s; 102 durationInfo.endTime = this._inst[i].s + this._inst[i].dur; 103 durationInfo.duration = this._inst[i].dur; 104 105 params.duration = durationInfo 106 resolveLocInfo.inst = this._inst[i]; 107 108 // Get locations that are available for this conflict's startTime to endTime 109 locInfo = this._assistantView.computeLocationAvailability(durationInfo, params); 110 resolveLocInfo.alternateLocationInfo = locInfo.locations; 111 // Add to the list for display by the ZmResolveLocationView 112 this._resolveLocList.add(resolveLocInfo); 113 } 114 } 115 params.list = this._resolveLocList; 116 this._resolveLocationView.set(params); 117 118 }; 119 120 ZmResolveLocationConflictDialog.prototype._handleOkButton = 121 function(event) { 122 var alteredLocations = {}; 123 var locationExceptions = {}; 124 var location; 125 var newLocation; 126 var resolveInfo; 127 128 for (var i = 0; i < this._resolveLocList.size(); i++) { 129 resolveInfo = this._resolveLocList.get(i); 130 if (resolveInfo.enabled) { 131 // Get the selected alternate (if any) 132 newLocation = this._resolveLocationView.getAlternateLocation(i); 133 } else { 134 // Pulldown was not used due to multiple locations already set for entry 135 newLocation = resolveInfo.originalLocation; 136 } 137 if (newLocation != ZmResolveLocationView.NO_SELECTION) { 138 location = this._composeView.getAttendeesFromString(ZmCalBaseItem.LOCATION, newLocation, false); 139 if (location) { 140 locationExceptions[resolveInfo.inst.s] = location.getArray(); 141 } 142 if (newLocation != resolveInfo.originalLocation) { 143 // Location changed - pass to caller to apply upon Save 144 alteredLocations[resolveInfo.inst.s] = locationExceptions[resolveInfo.inst.s]; 145 } 146 } 147 148 } 149 150 this.popdown(); 151 if(this._okCallback) this._okCallback.run(locationExceptions, alteredLocations); 152 153 }; 154 155 ZmResolveLocationConflictDialog.prototype._handleCancelButton = 156 function(event) { 157 this.popdown(); 158 }; 159 160 ZmResolveLocationConflictDialog.prototype.popup = 161 function(appt, inst, locationExceptions) { 162 this._appt = appt; 163 this._inst = inst ? inst : []; 164 165 // Existing set of location exceptions - either persisted to the DB, or specified 166 // by a previous use of this dialog. 167 this._locationExceptions = locationExceptions ? locationExceptions : {}; 168 169 DwtDialog.prototype.popup.call(this); 170 this._resolveLocationView.setLoadingHtml(); 171 172 // Use the assistantView to get sets of locations for each conflict date. 173 // These will be used to populate the alternative location dropdown. 174 var fbEndTime = 0; 175 if (this._inst.length > 0) { 176 var inst = this._inst[this._inst.length-1]; 177 fbEndTime = inst.s + inst.dur; 178 this._assistantView.getLocationFBInfo( 179 this._determineAlternateLocations, this, fbEndTime); 180 } 181 }; 182 183 ZmResolveLocationConflictDialog.prototype.setContent = 184 function(text) { 185 var contentDiv = this._getContentDiv(); 186 187 this._resolveLocationView = new ZmResolveLocationView( 188 this, this._controller, this._apptView); 189 this._resolveLocationView.reparentHtmlElement(contentDiv); 190 191 192 }; 193 194 ZmResolveLocationConflictDialog.prototype.cleanup = 195 function() { 196 if(this._resolveLocationView) this._resolveLocationView.removeAll(); 197 }; 198 199 200 201