1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * This class represents the export base view. 26 * 27 * @extends DwtForm 28 * @private 29 */ 30 ZmImportExportBaseView = function(params) { 31 if (arguments.length == 0) return; 32 DwtForm.call(this, params); 33 this.setScrollStyle(DwtControl.VISIBLE); 34 this._initSubType(ZmImportExportController.TYPE_CSV); 35 this._setFolderButton(appCtxt.getById(ZmOrganizer.ID_ROOT)); 36 }; 37 ZmImportExportBaseView.prototype = new DwtForm; 38 ZmImportExportBaseView.prototype.constructor = ZmImportExportBaseView; 39 40 ZmImportExportBaseView.prototype.toString = function() { 41 return "ZmImportExportBaseView"; 42 }; 43 44 // 45 // Data 46 // 47 48 ZmImportExportBaseView.prototype._folderId = -1; 49 50 // 51 // Public methods 52 // 53 54 ZmImportExportBaseView.prototype.getFolderId = function() { 55 return this._folderId; 56 }; 57 58 // DwtForm methods 59 60 ZmImportExportBaseView.prototype.update = function() { 61 DwtForm.prototype.update.apply(this, arguments); 62 63 // update type hint 64 var type = this.getValue("TYPE", ZmImportExportController.TYPE_TGZ); 65 this.setValue("TYPE_HINT", this.TYPE_HINTS[type]); 66 }; 67 68 ZmImportExportBaseView.prototype.setValue = function(name, value) { 69 var ovalue = this.getValue(name); 70 DwtForm.prototype.setValue.apply(this, arguments); 71 if (name == "TYPE" && value != ovalue) { 72 var type = value; 73 this._initSubType(type); 74 var isTgz = type == ZmImportExportController.TYPE_TGZ; 75 this.setEnabled("ADVANCED", isTgz); 76 if (this.getValue("ADVANCED") && !isTgz) { 77 this.setValue("ADVANCED", false); 78 this.update(); 79 } 80 var folder; 81 switch (type) { 82 case ZmImportExportController.TYPE_CSV: { 83 // TODO: Does this work for child accounts w/ fully-qualified ids? 84 folder = appCtxt.getById(ZmOrganizer.ID_ADDRBOOK); 85 break; 86 } 87 case ZmImportExportController.TYPE_ICS: { 88 folder = appCtxt.getById(ZmOrganizer.ID_CALENDAR); 89 break; 90 } 91 case ZmImportExportController.TYPE_TGZ: { 92 folder = appCtxt.getById(ZmOrganizer.ID_ROOT); 93 break; 94 } 95 } 96 this._setFolderButton(folder); 97 } 98 }; 99 100 // 101 // Protected methods 102 // 103 104 // initializers 105 106 ZmImportExportBaseView.prototype._initSubType = function(type) { 107 var select = this.getControl("SUBTYPE"); 108 if (!select) return; 109 110 var options = this._getSubTypeOptions(type); 111 if (!options || options.length == 0) return; 112 113 select.clearOptions(); 114 for (var i = 0; i < options.length; i++) { 115 select.addOption(options[i]); 116 } 117 select.setSelectedValue(options[0].value); 118 }; 119 120 ZmImportExportBaseView.prototype._getSubTypeOptions = function(type) { 121 if (!ZmImportExportBaseView.prototype.TGZ_OPTIONS) { 122 ZmImportExportBaseView.prototype.TGZ_OPTIONS = [ 123 { displayValue: ZmMsg["zimbra-tgz"], value: "zimbra-tgz" } 124 ]; 125 ZmImportExportBaseView.prototype.CSV_OPTIONS = []; 126 var formats = appCtxt.get(ZmSetting.AVAILABLE_CSVFORMATS); 127 for (var i = 0; i < formats.length; i++) { 128 var format = formats[i]; 129 if (format) { 130 ZmImportExportBaseView.prototype.CSV_OPTIONS.push( 131 { displayValue: ZmMsg[format] || format, value: format } 132 ); 133 } 134 } 135 ZmImportExportBaseView.prototype.ICS_OPTIONS = [ 136 { displayValue: ZmMsg["zimbra-ics"], value: "zimbra-ics" } 137 ]; 138 } 139 var options; 140 switch (type) { 141 case ZmImportExportController.TYPE_TGZ: { 142 options = this.TGZ_OPTIONS; 143 break; 144 } 145 case ZmImportExportController.TYPE_CSV: { 146 options = this.CSV_OPTIONS; 147 break; 148 } 149 case ZmImportExportController.TYPE_ICS: { 150 options = this.ICS_OPTIONS; 151 break; 152 } 153 } 154 return options; 155 }; 156 157 // handlers 158 159 ZmImportExportBaseView.prototype._type_onclick = function(radioId, groupId) { 160 // enable advanced options 161 var type = this.getValue("TYPE"); 162 this.setValue("TYPE", type); 163 }; 164 165 ZmImportExportBaseView.prototype._folderButton_onclick = function() { 166 // init state 167 if (!this._handleFolderDialogOkCallback) { 168 this._handleFolderDialogOkCallback = new AjxCallback(this, this._handleFolderDialogOk); 169 } 170 171 if (!this._TREES) { 172 this._TREES = {}; 173 this._TREES[ZmImportExportController.TYPE_TGZ] = []; 174 for (var org in ZmOrganizer.VIEWS) { 175 if (org == ZmId.APP_VOICE){ 176 continue; //Skip voice folders for import/export (Bug: 72269) 177 } 178 var settingId = ZmApp.SETTING[ZmOrganizer.APP2ORGANIZER_R[org]]; 179 if (settingId == null || appCtxt.get(settingId)) { 180 this._TREES[ZmImportExportController.TYPE_TGZ].push(org); 181 } 182 } 183 this._TREES[ZmImportExportController.TYPE_CSV] = appCtxt.get(ZmSetting.CONTACTS_ENABLED) ? [ZmOrganizer.ADDRBOOK] : []; 184 this._TREES[ZmImportExportController.TYPE_ICS] = appCtxt.get(ZmSetting.CALENDAR_ENABLED) ? [ZmOrganizer.CALENDAR] : []; 185 } 186 187 // pop-up dialog 188 var dialog = appCtxt.getChooseFolderDialog(); 189 dialog.registerCallback(DwtDialog.OK_BUTTON, this._handleFolderDialogOkCallback); 190 var type = this.getValue("TYPE") || ZmImportExportController.TYPE_TGZ; 191 var acctName = appCtxt.multiAccounts ? appCtxt.getActiveAccount().name : ""; 192 var params = { 193 treeIds: this._TREES[type], 194 overviewId: dialog.getOverviewId([this.toString(), type, acctName].join("_")), 195 description: "", 196 skipReadOnly: true, 197 omit: {}, 198 forceSingle: true, 199 showDrafts: (this instanceof ZmExportView), 200 hideNewButton: (this instanceof ZmExportView) 201 }; 202 params.omit[ZmOrganizer.ID_TRASH] = true; 203 dialog.popup(params); 204 }; 205 206 ZmImportExportBaseView.prototype._handleFolderDialogOk = function(folder) { 207 appCtxt.getChooseFolderDialog().popdown(); 208 this._setFolderButton(folder); 209 return true; 210 }; 211 212 ZmImportExportBaseView.prototype._setFolderButton = function(folder) { 213 // NOTE: Selecting a header is the same as "all folders" 214 this._folderId = folder ? folder.id : -1; 215 if (folder) { 216 var isRoot = folder.nId == ZmOrganizer.ID_ROOT; 217 this.setLabel("FOLDER_BUTTON", isRoot ? ZmMsg.allFolders : AjxStringUtil.htmlEncode(folder.name)); 218 } 219 else { 220 this.setLabel("FOLDER_BUTTON", ZmMsg.browse); 221 } 222 }; 223 224 // 225 // Class 226 // 227 228 ZmImportExportDataTypes = function(params) { 229 if (arguments.length == 0) return; 230 DwtComposite.apply(this, arguments); 231 this._tabGroup = new DwtTabGroup(this._htmlElId); 232 this._createHtml(); 233 }; 234 ZmImportExportDataTypes.prototype = new DwtComposite; 235 ZmImportExportDataTypes.prototype.constructor = ZmImportExportDataTypes; 236 237 ZmImportExportDataTypes.prototype.toString = function() { 238 return "ZmImportExportDataTypes"; 239 }; 240 241 // Data 242 243 ZmImportExportDataTypes.prototype.TEMPLATE = "data.ImportExport#DataTypes"; 244 245 // Public methods 246 247 ZmImportExportDataTypes.prototype.getTabGroupMember = function() { 248 return this._tabGroup; 249 }; 250 251 ZmImportExportDataTypes.prototype.setValue = function(value) { 252 // NOTE: Special case "" as *all* types -- this will include things 253 // like conversations, etc, that are implicitly added if no 254 // data types are specified for import/export. 255 if (value == "") { 256 var children = this.getChildren(); 257 for (var i = 0; i < children.length; i++) { 258 var checkbox = children[i]; 259 checkbox.setSelected(true); 260 } 261 return; 262 } 263 264 // return only those types that are checked 265 var types = value ? value.split(",") : []; 266 var type = {}; 267 for (var i = 0; i < types.length; i++) { 268 type[types[i]] = true; 269 } 270 var children = this.getChildren(); 271 for (var i = 0; i < children.length; i++) { 272 var checkbox = children[i]; 273 var selected = true; 274 var types = checkbox.getValue().split(","); 275 for (var j = 0; j < types.length; j++) { 276 if (!type[types[j]]) { 277 selected = false; 278 break; 279 } 280 } 281 checkbox.setSelected(selected); 282 } 283 }; 284 285 ZmImportExportDataTypes.prototype.getValue = function() { 286 // NOTE: Special case "" as *all* types. 287 if (this.isAllSelected()) { 288 return ""; 289 } 290 291 var types = []; 292 var children = this.getChildren(); 293 for (var i = 0; i < children.length; i++) { 294 var checkbox = children[i]; 295 if (checkbox.isSelected()) { 296 types.push(checkbox.getValue()); 297 } 298 } 299 return types.join(","); 300 }; 301 302 /** 303 * Checks if "all" is selected. 304 * 305 * @return {Boolean} <code>true</code> if all is selected 306 */ 307 ZmImportExportDataTypes.prototype.isAllSelected = function() { 308 var children = this.getChildren(); 309 for (var i = 0; i < children.length; i++) { 310 var checkbox = children[i]; 311 if (!checkbox.isSelected()) { 312 return false; 313 } 314 } 315 return true; 316 }; 317 318 ZmImportExportDataTypes.prototype.setEnabled = function(enabled) { 319 DwtComposite.prototype.setEnabled.apply(this, arguments); 320 var children = this.getChildren(); 321 for (var i = 0; i < children.length; i++) { 322 var checkbox = children[i]; 323 checkbox.setEnabled(enabled); 324 } 325 }; 326 327 // Protected methods 328 329 ZmImportExportDataTypes.prototype._createHtml = function(templateId) { 330 this._createHtmlFromTemplate(templateId || this.TEMPLATE, {id:this._htmlElId}); 331 }; 332 333 ZmImportExportDataTypes.prototype._createHtmlFromTemplate = 334 function(templateId, data) { 335 // get number of checkboxes 336 data.count = 0; 337 for (var appName in ZmApp.ORGANIZER) { 338 var orgType = ZmApp.ORGANIZER[appName]; 339 var views = ZmOrganizer.VIEWS[orgType]; 340 if (!views || views.length == 0) continue; 341 data.count++; 342 } 343 344 // create cells 345 DwtComposite.prototype._createHtmlFromTemplate.call(this, templateId, data); 346 347 // create checkboxes and place in cells 348 var i = 0; 349 for (var appName in ZmApp.ORGANIZER) { 350 var orgType = ZmApp.ORGANIZER[appName]; 351 var views = ZmOrganizer.VIEWS[orgType]; 352 if (!views || views.length == 0) continue; 353 354 var checkbox = new ZmImportExportDataTypeCheckbox({parent:this,checked:true}); 355 checkbox.setImage(ZmApp.ICON[appName]); 356 checkbox.setText(ZmMsg[ZmApp.NAME[appName]] || ZmApp.NAME[appName] || appName); 357 // NOTE: I know it's the default join string but I prefer 358 // explicit behavior. 359 checkbox.setValue(views.join(",")); 360 checkbox.replaceElement(data.id+"_cell_"+i); 361 362 this._tabGroup.addMember(checkbox); 363 364 i++; 365 } 366 }; 367 368 // 369 // Class 370 // 371 372 ZmImportExportDataTypeCheckbox = function(params) { 373 if (arguments.length == 0) return; 374 DwtCheckbox.apply(this, arguments); 375 }; 376 ZmImportExportDataTypeCheckbox.prototype = new DwtCheckbox; 377 ZmImportExportDataTypeCheckbox.prototype.constructor = ZmImportExportDataTypeCheckbox; 378 379 // Data 380 381 ZmImportExportDataTypeCheckbox.prototype.TEMPLATE = "data.ImportExport#DataTypeCheckbox"; 382 383 // Public methods 384 385 ZmImportExportDataTypeCheckbox.prototype.setTextPosition = function(position) { 386 DwtCheckbox.prototype.setTextPosition.call(this, DwtCheckbox.TEXT_RIGHT); 387 }; 388 389 ZmImportExportDataTypeCheckbox.prototype.setImage = function(imageName) { 390 if (this._imageEl) { 391 this._imageEl.className = AjxImg.getClassForImage(imageName); 392 } 393 }; 394 395 // Protected methods 396 397 ZmImportExportDataTypeCheckbox.prototype._createHtmlFromTemplate = 398 function(templateId, data) { 399 DwtCheckbox.prototype._createHtmlFromTemplate.apply(this, arguments); 400 this._imageEl = document.getElementById(data.id+"_image"); 401 }; 402