1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 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) 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * @overview
 26  */
 27 
 28 /**
 29  * Creates a time/location suggestion preference  dialog.
 30  * @class
 31  * This class represents a time/location preference dialog.
 32  *
 33  * @param	{DwtControl}	parent		the parent
 34  * @param	{String}	className		the class name
 35  *
 36  * @extends		DwtDialog
 37  */
 38 ZmTimeSuggestionPrefDialog = function(parent, className) {
 39 
 40     this._prefs = {};
 41     this._prefFields = {};
 42     this._prefLoaded = false;
 43 
 44 	className = className || "ZmTimeSuggestionPrefDialog";
 45 	DwtDialog.call(this, {parent:parent, className:className, title:ZmMsg.suggestionPreferences});
 46 
 47 	this.setButtonListener(DwtDialog.OK_BUTTON, new AjxListener(this, this._handleOkButton));
 48 	this.setButtonListener(DwtDialog.CANCEL_BUTTON, new AjxListener(this, this._handleCancelButton));
 49 
 50 };
 51 
 52 ZmTimeSuggestionPrefDialog.prototype = new DwtDialog;
 53 ZmTimeSuggestionPrefDialog.prototype.constructor = ZmTimeSuggestionPrefDialog;
 54 
 55 // Constants
 56 
 57 ZmTimeSuggestionPrefDialog.META_DATA_KEY = "MD_LOCATION_SEARCH_PREF";
 58 ZmTimeSuggestionPrefDialog.PREF_FIELDS = ["name", "site", "capacity", "building", "desc", "floor",
 59                                           "my_working_hrs_pref", "others_working_hrs_pref",
 60                                           "recurrenceSelect"];
 61 
 62 // corresponding attributes for search command
 63 ZmTimeSuggestionPrefDialog.SF_ATTR = {};
 64 ZmTimeSuggestionPrefDialog.SF_ATTR["name"]		  = "fullName";
 65 ZmTimeSuggestionPrefDialog.SF_ATTR["capacity"]	  = "zimbraCalResCapacity";
 66 ZmTimeSuggestionPrefDialog.SF_ATTR["desc"]        = "description";
 67 ZmTimeSuggestionPrefDialog.SF_ATTR["site"]		  = "zimbraCalResSite";
 68 ZmTimeSuggestionPrefDialog.SF_ATTR["building"]	  = "zimbraCalResBuilding";
 69 ZmTimeSuggestionPrefDialog.SF_ATTR["floor"]		  = "zimbraCalResFloor";
 70 
 71 // search field compares ops - listed here if not substring ("has")
 72 ZmTimeSuggestionPrefDialog.SF_OP = {};
 73 ZmTimeSuggestionPrefDialog.SF_OP["capacity"]	= "ge";
 74 ZmTimeSuggestionPrefDialog.SF_OP["floor"]		= "eq";
 75 
 76 ZmTimeSuggestionPrefDialog.MY_WORKING_HOURS_FIELD = 'my_working_hrs_pref';
 77 ZmTimeSuggestionPrefDialog.OTHERS_WORKING_HOURS_FIELD = 'others_working_hrs_pref';
 78 ZmTimeSuggestionPrefDialog.RECURRENCE = 'recurrenceSelect';
 79 
 80 ZmTimeSuggestionPrefDialog.CHECKBOX_FIELDS = {};
 81 ZmTimeSuggestionPrefDialog.CHECKBOX_FIELDS[ZmTimeSuggestionPrefDialog.MY_WORKING_HOURS_FIELD]      = true;
 82 ZmTimeSuggestionPrefDialog.CHECKBOX_FIELDS[ZmTimeSuggestionPrefDialog.OTHERS_WORKING_HOURS_FIELD]   = true;
 83 
 84 ZmTimeSuggestionPrefDialog.DEFAULT_VAL = {};
 85 ZmTimeSuggestionPrefDialog.DEFAULT_VAL[ZmTimeSuggestionPrefDialog.MY_WORKING_HOURS_FIELD]    = 'true';
 86 ZmTimeSuggestionPrefDialog.DEFAULT_VAL[ZmTimeSuggestionPrefDialog.OTHERS_WORKING_HOURS_FIELD] = 'true';
 87 ZmTimeSuggestionPrefDialog.DEFAULT_NUM_RECURRENCE = 4;
 88 ZmTimeSuggestionPrefDialog.MAX_NUM_RECURRENCE = 10;
 89 ZmTimeSuggestionPrefDialog.DEFAULT_VAL[ZmTimeSuggestionPrefDialog.RECURRENCE] =
 90     ZmTimeSuggestionPrefDialog.DEFAULT_NUM_RECURRENCE.toString();
 91 
 92 
 93 // Public methods
 94 
 95 ZmTimeSuggestionPrefDialog.prototype.toString =
 96 function() {
 97 	return "ZmTimeSuggestionPrefDialog";
 98 };
 99 
100 ZmTimeSuggestionPrefDialog.prototype._handleOkButton =
101 function(event) {
102     this.readPrefs();
103     this.setSearchPreference();
104     this.popdown();
105     if(this._callback) this._callback.run();
106 };
107 
108 ZmTimeSuggestionPrefDialog.prototype._handleCancelButton =
109 function(event) {
110 	this.popdown();
111 };
112 
113 
114 
115 /**
116  * Pops-up the properties dialog.
117  *
118  */
119 ZmTimeSuggestionPrefDialog.prototype.popup =
120 function(account) {
121     this._account = account;
122 	DwtDialog.prototype.popup.call(this);
123     this.getSearchPreference();
124 
125 	var el = document.getElementById(this._htmlElId);
126 	var loc = Dwt.getLocation(el);
127 	if (loc.x < 0) {
128 		// For Bug 94520.  Japanese text is not getting formatted properly (it stays one very long string), until the
129 		// dialog was dragged.  Dragging runs the next line in its code (which places the left of the dialog on screen)
130 		// and it triggers the reformatting.
131 		// Don't try setting the location via the loc var to DwtDialog.popup - the DwtBaseDialog positioning 'corrects'
132 		// it and resets it to an offscreen value.
133 		el.style.left = "0px";
134 	}
135 };
136 
137 ZmTimeSuggestionPrefDialog.prototype.popdown =
138 function() {
139 	DwtDialog.prototype.popdown.call(this);
140 };
141 
142 ZmTimeSuggestionPrefDialog.prototype.getPrefLoaded =
143 function() {
144     return this._prefLoaded;
145 }
146 
147 ZmTimeSuggestionPrefDialog.prototype._getContentHtml =
148 function() {
149     return AjxTemplate.expand("calendar.Appointment#TimeLocationPreference", {id: this.getHTMLElId()});
150 };
151 
152 ZmTimeSuggestionPrefDialog.prototype.setContent =
153 function(text) {
154 	var d = this._getContentDiv();
155 	if (d) {
156 		d.innerHTML = text || "";
157 	}
158 
159     this._recurrenceSelect = new DwtSelect({id:this._htmlElId + "_recurrenceSelect",
160                                 parent:this, parentElement:(this._htmlElId + "_recurrence")});
161     for (var i = 1; i <= ZmTimeSuggestionPrefDialog.MAX_NUM_RECURRENCE; i++) {
162         this._recurrenceSelect.addOption(i.toString(), (i == 1), i);
163     }
164 
165 
166     this._dlgId = AjxCore.assignId(this);
167 
168     var element, id;
169     for(var i=0; i<ZmTimeSuggestionPrefDialog.PREF_FIELDS.length; i++) {
170         id = ZmTimeSuggestionPrefDialog.PREF_FIELDS[i];
171         element = document.getElementById(this.getHTMLElId() + "_" + id);
172         if (element) {
173             this._prefFields[id] = element;
174             this._prefs[id] = this.getPreferenceFieldValue(id);
175         }
176     }
177 };
178 
179 ZmTimeSuggestionPrefDialog.prototype.getPreference =
180 function(id) {
181     return (this._prefs[id] != null) ? this._prefs[id] : ZmTimeSuggestionPrefDialog.DEFAULT_VAL[id];
182 };
183 
184 ZmTimeSuggestionPrefDialog.prototype.setCallback =
185 function(callback) {
186     this._callback = callback;
187 };
188 
189 ZmTimeSuggestionPrefDialog.prototype.readPrefs =
190 function(text) {
191     var field;
192     for(var id in this._prefFields) {
193         this._prefs[id] = this.getPreferenceFieldValue(id)
194     }
195 };
196 
197 ZmTimeSuggestionPrefDialog.prototype.getPreferenceFieldValue =
198 function(id) {
199     if (id == "recurrenceSelect") {
200         return this._recurrenceSelect.getValue();
201     } else {
202         var field = this._prefFields[id];
203         if(!field) return;
204 
205         if(ZmTimeSuggestionPrefDialog.CHECKBOX_FIELDS[id]){
206             return field.checked ? 'true' : 'false';
207         }else {
208             return field.value;
209         }
210     }
211 };
212 
213 ZmTimeSuggestionPrefDialog.prototype.setPreferenceFieldValue =
214 function(id, value) {
215     if (id == "recurrenceSelect") {
216        this._recurrenceSelect.setSelectedValue(value);
217     } else {
218         var field = this._prefFields[id];
219         if(!field) return;
220 
221         if(ZmTimeSuggestionPrefDialog.CHECKBOX_FIELDS[id]){
222             field.checked = (value == 'true');
223         }else {
224             field.value = value || "";
225         }
226     }
227 };
228 
229 ZmTimeSuggestionPrefDialog.prototype.getSearchPreference =
230 function(account, prefSearchCallback) {
231     var md = new ZmMetaData(account || this._account);
232     var callback = new AjxCallback(this, this.processSearchPreference, [prefSearchCallback]);
233     md.get(ZmTimeSuggestionPrefDialog.META_DATA_KEY, null, callback);
234 };
235 
236 ZmTimeSuggestionPrefDialog.prototype.processSearchPreference =
237 function(prefSearchCallback, metadataResponse) {
238     this._prefs = {};
239 
240     var objPrefs = metadataResponse.getResponse().BatchResponse.GetMailboxMetadataResponse[0].meta[0]._attrs;
241     for (name in objPrefs) {
242         if(name && objPrefs[name]) {
243             this._prefs[name] = objPrefs[name];
244             this.setPreferenceFieldValue(name, this._prefs[name]);
245         }
246     }
247 
248     //set default value for the preferences
249     for(var id in ZmTimeSuggestionPrefDialog.DEFAULT_VAL) {
250         if(!this._prefs[id]) {
251             this.setPreferenceFieldValue(id, ZmTimeSuggestionPrefDialog.DEFAULT_VAL[id]);            
252         }
253     }
254 
255     this._prefLoaded = true;
256     if(prefSearchCallback) prefSearchCallback.run();
257 };
258 
259 ZmTimeSuggestionPrefDialog.prototype.setSearchPreference =
260 function() {
261     var md = new ZmMetaData(this._account);
262     var newPrefs = {};
263     for(var id in this._prefs) {
264         if(this._prefs[id] != "") newPrefs[id] = this._prefs[id];
265     }
266     return md.set(ZmTimeSuggestionPrefDialog.META_DATA_KEY, newPrefs);
267 };
268 
269 ZmTimeSuggestionPrefDialog.isSearchCondition =
270 function(id) {
271     return Boolean(ZmTimeSuggestionPrefDialog.SF_ATTR[id]);
272 };
273 
274 ZmTimeSuggestionPrefDialog.prototype.handleRoomCheckbox =
275 function() {
276     this.enableLocationFields(true);
277 };
278 
279 ZmTimeSuggestionPrefDialog.prototype.enableLocationFields =
280 function(enable) {
281     for(var id in ZmTimeSuggestionPrefDialog.SF_ATTR) {
282         if(!this._prefFields[id]) continue;
283         this._prefFields[id].disabled = !enable;
284     }
285 };
286 
287 ZmTimeSuggestionPrefDialog._handleRoomCheckbox =
288 function(ev) {
289 	var el = DwtUiEvent.getTarget(ev);
290 	var dlg = AjxCore.objectWithId(el._dlgId);
291 	if (!dlg) { return; }
292     dlg.handleRoomCheckbox();
293 };