1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * Creates a Back-up preference page. 26 * @constructor 27 * @class ZmBackupPage 28 * This class represents a page that allows the user to set preferences on backup 29 * For Instance, How often user wants to backup data and list of accounts user wants to back-up 30 * 31 * @author KK 32 * 33 * @param {DwtControl} parent the containing widget 34 * @param {Object} section the page 35 * @param {ZmPrefController} controller the prefs controller 36 * 37 * @extends ZmPreferencesPage 38 * @private 39 */ 40 ZmBackupPage = function(parent, section, controller) { 41 ZmPreferencesPage.call(this, parent, section, controller); 42 //this.backupDetailsLoaded = false; 43 }; 44 45 ZmBackupPage.prototype = new ZmPreferencesPage; 46 ZmBackupPage.prototype.constructor = ZmBackupPage; 47 48 ZmBackupPage.prototype.toString = 49 function () { 50 return "ZmBackupPage"; 51 }; 52 53 ZmBackupPage.prototype.showMe = 54 function(){ 55 ZmPreferencesPage.prototype.showMe.call(this); 56 if (this._acctListView) { 57 var s = this._acctListView.getSelection(); 58 this._acctListView.set(this.getAccounts()._vector.clone()); 59 if (s && s[0]) { 60 this._acctListView.setSelection(s[0]); 61 } 62 } 63 64 if (this._restoreListView) { 65 var r = this._restoreListView.getSelection(); 66 this._restoreListView.set(this.getBackups(true)._vector.clone()); 67 if (r && r[0]) { 68 this._restoreListView.setSelection(r[0]); 69 } 70 } 71 }; 72 73 74 /** 75 * @private 76 */ 77 ZmBackupPage.prototype._setupCustom = 78 function(id, setup, value) { 79 80 if (id == ZmSetting.OFFLINE_BACKUP_ACCOUNT_ID) { 81 this._acctListView = new ZmPrefAcctListView(this, this._controller); 82 return this._acctListView; 83 } 84 85 if (id == ZmSetting.OFFLINE_BACKUP_RESTORE) { 86 this._restoreListView = new ZmPrefBackupListView(this, this._controller); 87 return this._restoreListView; 88 } 89 90 return ZmPreferencesPage.prototype._setupCustom.apply(this, arguments); 91 }; 92 93 ZmBackupPage.prototype._createControls = 94 function() { 95 96 // add "Backup" button 97 this._backupButton = new DwtButton({parent:this, parentElement: this._htmlElId+"_button"}); 98 this._backupButton.setText(ZmMsg.offlineBackUpButton); 99 this._backupButton.addSelectionListener(new AjxListener(this, this._handleBackupAccountsButton)); 100 101 this._restoreButton = new DwtButton({parent:this, parentElement: this._htmlElId+"_restore_button"}); 102 this._restoreButton.setText(ZmMsg.offlineBackUpRestore); 103 this._restoreButton.addSelectionListener(new AjxListener(this, this._handleRestoreBackupButton)); 104 105 ZmPreferencesPage.prototype._createControls.apply(this, arguments); 106 }; 107 108 ZmBackupPage.prototype._handleBackupAccountsButton = 109 function() { 110 this._backupButton.setEnabled(false); 111 112 var accts = this.getAccounts()._vector.getArray(); 113 114 var settingsObj = appCtxt.getSettings(); 115 var setting = settingsObj.getSetting(ZmSetting.OFFLINE_BACKUP_ACCOUNT_ID); 116 117 var checked = []; 118 for (var i = 0; i < accts.length; i++) { 119 if (accts[i].active) { 120 checked.push(accts[i].id); 121 } 122 } 123 if(checked.length < 1) { 124 this._backupButton.setEnabled(true); 125 return; 126 } 127 128 setting.setValue(checked); 129 130 var soapDoc = AjxSoapDoc.create("BatchRequest", "urn:zimbra", null); 131 soapDoc.setMethodAttribute("onerror", "continue"); 132 for (var k=0; k<checked.length; k++) { 133 var requestNode = soapDoc.set("AccountBackupRequest",null,null,"urn:zimbraOffline"); 134 requestNode.setAttribute("id", checked[k]); 135 } 136 137 var params = { 138 soapDoc: soapDoc, 139 asyncMode: true, 140 errorCallback: null, 141 accountName: appCtxt.accountList.mainAccount.name 142 }; 143 144 params.callback = new AjxCallback(this, this._handleBackupStarted); 145 var appController = appCtxt.getAppController(); 146 appController.sendRequest(params); 147 }; 148 149 ZmBackupPage._handleBackupNowLink = 150 function(id, obj) { 151 var backupPage = DwtControl.fromElementId(obj); 152 backupPage._handleBackupNowLink(id); 153 }; 154 155 ZmBackupPage.prototype._handleBackupNowLink = 156 function(id) { 157 158 try{ 159 var soapDoc = AjxSoapDoc.create("AccountBackupRequest", "urn:zimbraOffline"); 160 var method = soapDoc.getMethod(); 161 method.setAttribute("id", id); 162 var respCallback = new AjxCallback(this, this._handleBackupAcctStarted , id); 163 var params = { 164 soapDoc:soapDoc, 165 callback:respCallback, 166 asyncMode:true 167 }; 168 appCtxt.getAppController().sendRequest(params); 169 } 170 finally { // do 171 return false; 172 } 173 }; 174 175 ZmBackupPage.prototype._handleBackupAcctStarted = 176 function(id) { 177 appCtxt.setStatusMsg(AjxMessageFormat.format(ZmMsg.offlineBackupStartedForAcct, appCtxt.accountList.getAccount(id).getDisplayName())); 178 }; 179 180 ZmBackupPage.prototype._handleBackupStarted = 181 function(result) { 182 appCtxt.setStatusMsg(ZmMsg.offlineBackUpStarted); 183 this._backupButton.setEnabled(true); 184 }; 185 186 ZmBackupPage.prototype._handleRestoreBackupButton = 187 function() { 188 189 this._restoreButton.setEnabled(false); 190 191 var backups = this.getBackups()._vector.getArray(); 192 var sel = []; 193 for (var i = 0; i < backups.length; i++) { 194 if (backups[i].active) { 195 var bk = backups[i]; 196 sel.push(backups[i]); 197 break; 198 } 199 } 200 201 if(sel.length < 1) { 202 this._restoreButton.setEnabled(true); 203 return; 204 } 205 206 var soapDoc = AjxSoapDoc.create("AccountRestoreRequest", "urn:zimbraOffline"); 207 var method = soapDoc.getMethod(); 208 method.setAttribute("id", sel[0].acct); 209 method.setAttribute("time", sel[0].timestamp); 210 var respCallback = new AjxCallback(this, this._handleAccountRestoreSent, [sel[0].acct]); 211 var params = { 212 soapDoc:soapDoc, 213 callback:respCallback, 214 asyncMode:true 215 }; 216 appCtxt.getAppController().sendRequest(params); 217 218 }; 219 220 ZmBackupPage.prototype._handleAccountRestoreSent = 221 function(id, resp) { 222 223 this._restoreButton.setEnabled(true); 224 if(resp._data.AccountRestoreResponse.status == "restored") { 225 appCtxt.setStatusMsg(AjxMessageFormat.format(ZmMsg.offlineBackupRestored, appCtxt.accountList.getAccount(id).name)); 226 } 227 }; 228 229 ZmBackupPage.prototype.addCommand = 230 function(batchCommand) { 231 232 var soapDoc = AjxSoapDoc.create("ModifyPrefsRequest", "urn:zimbraAccount"); 233 var accts = this.getAccounts()._vector.getArray(); 234 235 var settingsObj = appCtxt.getSettings(); 236 var setting = settingsObj.getSetting(ZmSetting.OFFLINE_BACKUP_ACCOUNT_ID); 237 238 var checked = []; 239 for (var i = 0; i < accts.length; i++) { 240 if (accts[i].active) { 241 checked.push(accts[i].id); 242 } 243 } 244 var node = soapDoc.set("pref", checked.join(",")); 245 node.setAttribute("name", "zimbraPrefOfflineBackupAccountId"); 246 setting.setValue(checked.join(", ")); 247 batchCommand.addNewRequestParams(soapDoc); 248 }; 249 250 /** 251 * Gets the account preferences. 252 * 253 * @return {ZmPrefAccounts} the accounts 254 * 255 * @private 256 */ 257 258 259 ZmBackupPage.prototype.getAccounts = 260 function() { 261 if (!this._accounts) { 262 this._accounts = ZmBackupPage._getAccounts(); 263 } 264 return this._accounts; 265 }; 266 267 268 ZmBackupPage._getAccounts = 269 function() { 270 var savedAccounts = appCtxt.get(ZmSetting.OFFLINE_BACKUP_ACCOUNT_ID); 271 savedAccounts = (savedAccounts && savedAccounts.length) ? savedAccounts.split(",") : []; 272 var accounts = new ZmPrefAccounts(); 273 var visAccts = appCtxt.accountList.visibleAccounts; 274 for (var i=0; i< visAccts.length; i++) { 275 var name = visAccts[i].getDisplayName(); 276 var desc = visAccts[i].name; 277 var id = visAccts[i].id; 278 279 loop1: for (var k=0; k < savedAccounts.length ; k++) { 280 var checked = (id == AjxStringUtil.trim(savedAccounts[k])); 281 if(checked) { break loop1; } 282 } 283 accounts.addPrefAccount(new ZmPrefAccount(name, checked, desc, id)); 284 } 285 return accounts; 286 }; 287 288 ZmBackupPage.prototype._isChecked = 289 function(name) { 290 var z = this.getAccounts().getPrefAccountByName(name); 291 return (z && z.active); 292 }; 293 294 ZmBackupPage.prototype.isDirty = 295 function() { 296 var allAccountss = this.getAccounts(); 297 var r = false; 298 var arr = allAccountss._vector.getArray(); 299 for (var i = 0; i < arr.length; i++) { 300 if (arr[i]._origStatus != arr[i].active) { 301 r = true; 302 break; 303 } 304 } 305 return r; 306 }; 307 308 309 /** 310 * ZmPrefAcctListView 311 * 312 * @param parent 313 * @param controller 314 * @private 315 */ 316 ZmPrefAcctListView = function(parent, controller) { 317 318 DwtListView.call(this, { 319 parent: parent, 320 className: "ZmFilterListView", 321 headerList: this._getHeaderList(), 322 view: ZmId.OFFLINE_BACKUP_ACCOUNT_ID 323 }); 324 325 this._controller = controller; 326 this.setMultiSelect(false); // single selection only 327 this._internalId = AjxCore.assignId(this); 328 }; 329 330 ZmPrefAcctListView.COL_ACTIVE = "ac"; 331 ZmPrefAcctListView.COL_NAME = "na"; 332 ZmPrefAcctListView.COL_DESC = "ds"; 333 ZmPrefAcctListView.COL_ACTION = "an"; 334 ZmPrefAcctListView.CHECKBOX_PREFIX = "_accCheckbox"; 335 336 337 ZmPrefAcctListView.prototype = new DwtListView; 338 ZmPrefAcctListView.prototype.constructor = ZmPrefAcctListView; 339 340 ZmPrefAcctListView.prototype.toString = 341 function() { 342 return "ZmPrefAcctListView"; 343 }; 344 345 ZmPrefAcctListView.prototype.set = 346 function(list) { 347 this._checkboxIds = []; 348 DwtListView.prototype.set.call(this, list); 349 this._handleAccts(); 350 }; 351 352 ZmPrefAcctListView.prototype._handleAccts = function(evt) { 353 this._acctsLoaded = true; 354 var item = {}; 355 var visAccts = this.parent.getAccounts()._vector.getArray(); 356 for (var i=0; i< visAccts.length; i++) { 357 item.name = visAccts[i].name; 358 item.desc = visAccts[i].desc; 359 this.setCellContents(item, ZmPrefAcctListView.COL_NAME, AjxStringUtil.htmlEncode(AjxStringUtil.trim(item.name))); 360 this.setCellContents(item, ZmPrefAcctListView.COL_DESC, AjxStringUtil.htmlEncode(item.desc)); 361 } 362 }; 363 364 ZmPrefAcctListView.prototype.setCellContents = function(item, field, html) { 365 var el = this.getCellElement(item, field); 366 if (!el) { return; } 367 el.innerHTML = html; 368 }; 369 370 ZmPrefAcctListView.prototype.getCellElement = function(item, field) { 371 return document.getElementById(this._getCellId(item, field)); 372 }; 373 374 ZmPrefAcctListView.prototype._getCellId = function(item, field, params) { 375 return DwtId.getListViewItemId(DwtId.WIDGET_ITEM_CELL, "accts", AjxStringUtil.trim(item.name), field); 376 }; 377 378 ZmPrefAcctListView.prototype._getHeaderList = 379 function() { 380 return [ 381 (new DwtListHeaderItem({field:ZmPrefAcctListView.COL_ACTIVE, text:ZmMsg.active, width:ZmMsg.COLUMN_WIDTH_ACTIVE})), 382 (new DwtListHeaderItem({field:ZmPrefAcctListView.COL_NAME, text:ZmMsg.name, width:ZmMsg.COLUMN_WIDTH_FOLDER_DLV})), 383 (new DwtListHeaderItem({field:ZmPrefAcctListView.COL_DESC, text:ZmMsg.emailAddr, width:ZmMsg.COLUMN_WIDTH_FOLDER_DLV})), 384 (new DwtListHeaderItem({field:ZmPrefAcctListView.COL_ACTION, text:ZmMsg.action, width:ZmMsg.COLUMN_WIDTH_FOLDER_DLV})) 385 ]; 386 387 }; 388 389 ZmPrefAcctListView.prototype._getCellClass = 390 function(item, field, params) { 391 if (field == ZmPrefAcctListView.COL_ACTIVE) { 392 return "FilterActiveCell"; 393 } 394 return DwtListView.prototype._getCellClass.call(this, item, field, params); 395 }; 396 397 ZmPrefAcctListView.prototype._getCellContents = 398 function(html, idx, item, field, colIdx, params) { 399 if (field == ZmPrefAcctListView.COL_ACTIVE) { 400 html[idx++] = "<input name='OFFLINE_BACKUP_ACCOUNT_ID' type='checkbox' "; 401 html[idx++] = item.active ? "checked " : ""; 402 html[idx++] = "id='"; 403 html[idx++] = AjxStringUtil.trim(item.name); 404 html[idx++] = "_acctsCheckbox' _name='"; 405 html[idx++] = AjxStringUtil.trim(item.name); 406 html[idx++] = "' _acId='"; 407 html[idx++] = this._internalId; 408 html[idx++] = "' onclick='ZmPrefAcctListView._activeStateChange;'>"; 409 } else if (field == ZmPrefAcctListView.COL_DESC) { 410 html[idx++] = "<div id='"; 411 html[idx++] = this._getCellId(item, ZmPrefAcctListView.COL_DESC); 412 html[idx++] = "'>"; 413 html[idx++] = AjxStringUtil.stripTags(item.desc, true); 414 html[idx++] = "</div>"; 415 } else if (field == ZmPrefAcctListView.COL_NAME) { 416 html[idx++] = "<div id='"; 417 html[idx++] = this._getCellId(item, ZmPrefAcctListView.COL_NAME); 418 html[idx++] = "' title='"; 419 html[idx++] = item.name; 420 html[idx++] = "'>"; 421 html[idx++] = AjxStringUtil.stripTags(item.name, true); 422 html[idx++] = "</div>"; 423 } else if (field == ZmPrefAcctListView.COL_ACTION) { 424 html[idx++] = "<a href='javascript:;' onclick='ZmBackupPage._handleBackupNowLink("; 425 var accId = appCtxt.accountList.getAccountByName(AjxStringUtil.trim(item.desc)).id; 426 html[idx++] = '"' + accId.toString(); 427 html[idx++] = '","' + this.parent._htmlElId + '"'; 428 html[idx++] = ");'>"; 429 html[idx++] = ZmMsg.offlineBackUpNow; 430 html[idx++] = "</a>"; 431 } 432 433 return idx; 434 }; 435 436 437 /** 438 * Handles click of 'active' checkbox by toggling the rule's active state. 439 * 440 * @param ev [DwtEvent] click event 441 */ 442 ZmPrefAcctListView._activeStateChange = 443 function(ev) { 444 var target = DwtUiEvent.getTarget(ev); 445 var flvId = target.getAttribute("_acId"); 446 var flv = AjxCore.objectWithId(flvId); 447 var name = target.getAttribute("_name"); 448 var z = flv.parent.getAccounts().getPrefAccountByName(name); 449 if (z) { 450 z.active = !z.active; 451 } 452 }; 453 454 ZmPrefAcctListView.prototype._allowLeftSelection = 455 function(clickedEl, ev, button) { 456 var target = DwtUiEvent.getTarget(ev); 457 var isInput = (target.id.indexOf("_acctsCheckbox") > 0); 458 if (isInput) { 459 ZmPrefAcctListView._activeStateChange(ev); 460 } 461 462 return !isInput; 463 }; 464 465 /** 466 * Model class to hold the list of PrefAccounts 467 * @private 468 */ 469 ZmPrefAccounts = function() { 470 ZmModel.call(this, ZmEvent.S_PREF_ACCOUNT); 471 this._vector = new AjxVector(); 472 this._zNameHash = {}; 473 }; 474 475 ZmPrefAccounts.prototype = new ZmModel; 476 ZmPrefAccounts.prototype.constructor = ZmPrefAccounts; 477 478 ZmPrefAccounts.prototype.toString = 479 function() { 480 return "ZmPrefAccounts"; 481 }; 482 483 ZmPrefAccounts.prototype.addPrefAccount = 484 function(Account) { 485 this._vector.add(Account); 486 this._zNameHash[Account.name] = Account; 487 }; 488 489 ZmPrefAccounts.prototype.removePrefAccount = 490 function(Account) { 491 delete this._zNameHash[Account.name]; 492 this._vector.remove(Account); 493 }; 494 495 ZmPrefAccounts.prototype.getPrefAccountByName = 496 function(name) { 497 return this._zNameHash[name]; 498 }; 499 500 /** 501 * ZmPrefAccount 502 * 503 * @param name 504 * @param active 505 * @param desc 506 * 507 * @private 508 */ 509 ZmPrefAccount = function(name, active, desc, id) { 510 this.name = name; 511 this.active = (active !== false); 512 this.desc = desc; 513 this.id = id; 514 this._origStatus = this.active; 515 }; 516 517 ZmBackupPage.prototype.getBackups = 518 function(force) { 519 if (!this._backups || force) { 520 this._backups = ZmBackupPage._getBackups(); 521 } 522 return this._backups; 523 }; 524 525 526 ZmBackupPage._getBackups = 527 function(evt) { 528 529 var soapDoc = AjxSoapDoc.create("AccountBackupEnumerationRequest", "urn:zimbraOffline"); 530 var result = appCtxt.getAppController().sendRequest({soapDoc:soapDoc, asyncMode:false}); 531 532 var _restoreAccts = result.AccountBackupEnumerationResponse.account; 533 var backups = new ZmPrefBackups(); 534 for (var i=0; i< _restoreAccts.length; i++) { 535 var acct = _restoreAccts[i].id; 536 var backupArray = _restoreAccts[i].backup; 537 if(!backupArray) { 538 continue; 539 } 540 541 for(var k=0; k<backupArray.length; k++) { 542 var fileSize = backupArray[k].fileSize; 543 var timestamp = backupArray[k].time; 544 backups.addPrefBackup(new ZmPrefBackup(timestamp, false, fileSize, acct)); 545 } 546 547 } 548 return backups; 549 }; 550 551 /** 552 * ZmPrefBackupListView 553 * 554 * @param parent 555 * @param controller 556 * @private 557 */ 558 559 ZmPrefBackupListView = function(parent, controller) { 560 561 DwtListView.call(this, { 562 parent: parent, 563 className: "ZmFilterListView", 564 headerList: this._getHeaderList(), 565 view: ZmId.OFFLINE_BACKUP_RESTORE 566 }); 567 568 this._controller = controller; 569 this.setMultiSelect(false); // single selection only 570 this._internalId = AjxCore.assignId(this); 571 }; 572 573 ZmPrefBackupListView.COL_ACTIVE = "ac"; 574 ZmPrefBackupListView.COL_NAME = "na"; 575 ZmPrefBackupListView.COL_DESC = "ds"; 576 ZmPrefBackupListView.COL_ACTION = "an"; 577 ZmPrefBackupListView.CHECKBOX_PREFIX = "_BackupCheckbox"; 578 579 580 ZmPrefBackupListView.prototype = new DwtListView; 581 ZmPrefBackupListView.prototype.constructor = ZmPrefBackupListView; 582 583 ZmPrefBackupListView.prototype.toString = 584 function() { 585 return "ZmPrefBackupListView"; 586 }; 587 588 ZmPrefBackupListView.prototype.set = 589 function(list) { 590 this._checkboxIds = []; 591 DwtListView.prototype.set.call(this, list); 592 //this.loadBackupDetails(); 593 }; 594 595 ZmPrefBackupListView.prototype.loadBackupDetails = 596 function() { 597 var restoreArr = this.parent._backups._vector.getArray(); 598 var item = {}; 599 for (var i = 0; i < restoreArr.length; i++) { 600 item.timestamp = restoreArr[i].timestamp; 601 item.size = restoreArr[i].fileSize; 602 item.acct = restoreArr[i].acct; 603 this.setCellContents(item, ZmPrefBackupListView.COL_NAME, item.timestamp); 604 this.setCellContents(item, ZmPrefBackupListView.COL_DESC, item.size); 605 } 606 }; 607 608 ZmPrefBackupListView.prototype.setCellContents = function(item, field, html) { 609 var el = this.getCellElement(item, field); 610 if (!el) { return; } 611 el.innerHTML = html; 612 }; 613 614 ZmPrefBackupListView.prototype.getCellElement = function(item, field) { 615 return document.getElementById(this._getCellId(item, field)); 616 }; 617 618 ZmPrefBackupListView.prototype._getCellId = function(item, field, params) { 619 return DwtId.getListViewItemId(DwtId.WIDGET_ITEM_CELL, "backup", item.timestamp, field); 620 }; 621 622 623 ZmPrefBackupListView.prototype._getHeaderList = 624 function() { 625 return [ 626 (new DwtListHeaderItem({field:ZmPrefBackupListView.COL_ACTIVE, text:ZmMsg.active, width:ZmMsg.COLUMN_WIDTH_ACTIVE})), 627 (new DwtListHeaderItem({field:ZmPrefBackupListView.COL_NAME, text:ZmMsg.date, width:ZmMsg.COLUMN_WIDTH_FOLDER_DLV})), 628 (new DwtListHeaderItem({field:ZmPrefBackupListView.COL_DESC, text:ZmMsg.size, width:ZmMsg.COLUMN_WIDTH_FOLDER_DLV})), 629 (new DwtListHeaderItem({field:ZmPrefBackupListView.COL_ACTION, text:ZmMsg.account, width:ZmMsg.COLUMN_WIDTH_FOLDER_DLV})) 630 ]; 631 }; 632 633 ZmPrefBackupListView.prototype._getCellContents = 634 function(html, idx, item, field, colIdx, params) { 635 if (field == ZmPrefBackupListView.COL_ACTIVE) { 636 html[idx++] = "<input name='offline_backup_restore' type='checkbox' "; 637 html[idx++] = item.active ? "checked " : ""; 638 html[idx++] = "id='"; 639 html[idx++] = item.timestamp; 640 html[idx++] = "_"; 641 html[idx++] = item.acct; 642 html[idx++] = "_backupCheckbox' _name='"; 643 html[idx++] = item.timestamp; 644 html[idx++] = "_"; 645 html[idx++] = item.acct; 646 html[idx++] = "' _bkId='"; 647 html[idx++] = this._internalId; 648 html[idx++] = "' onchange='ZmPrefBackupListView._activeStateChange'>"; 649 } else if (field == ZmPrefBackupListView.COL_DESC) { 650 html[idx++] = "<div id='"; 651 html[idx++] = this._getCellId(item, ZmPrefBackupListView.COL_DESC); 652 html[idx++] = "'>"; 653 var fSize = item.fileSize; 654 var numFormater = AjxNumberFormat.getInstance(); 655 if (fSize != null && fSize >= 0) { 656 if (fSize < 1024) { //" B"; 657 fSize = numFormater.format(fSize) + " "+ZmMsg.b; 658 } 659 else if (fSize < (1024*1024) ) { //" KB"; 660 fSize = numFormater.format(Math.round((fSize / 1024) * 10) / 10) + " "+ZmMsg.kb; 661 } 662 else { //" MB"; 663 fSize = numFormater.format(Math.round((fSize / (1024*1024)) * 10) / 10) + " "+ZmMsg.mb; 664 } 665 } else { fSize = 0+" "+ZmMsg.b; } 666 html[idx++] = fSize; 667 html[idx++] = "</div>"; 668 } 669 else if (field == ZmPrefBackupListView.COL_NAME) { 670 html[idx++] = "<div id='"; 671 html[idx++] = this._getCellId(item, ZmPrefBackupListView.COL_NAME); 672 html[idx++] = "'>"; 673 html[idx++] = AjxDateFormat.getDateTimeInstance(AjxDateFormat.MEDIUM).format(new Date(item.timestamp)); 674 html[idx++] = "</div>"; 675 } 676 else if (field == ZmPrefBackupListView.COL_ACTION) { 677 html[idx++] = "<div id='"; 678 html[idx++] = this._getCellId(item, ZmPrefBackupListView.COL_ACTION); 679 html[idx++] = "'>"; 680 html[idx++] = appCtxt.accountList.getAccount(item.acct).name; 681 html[idx++] = "</div>"; 682 } 683 return idx; 684 }; 685 686 ZmPrefBackupListView._activeStateChange = 687 function(ev) { 688 var target = DwtUiEvent.getTarget(ev); 689 var bkId = target.getAttribute("_bkId"); 690 var bk = AjxCore.objectWithId(bkId); 691 var name = target.getAttribute("_name"); 692 var bkups = bk.parent.getBackups(); 693 var z = bkups.getPrefBackupByName(name); 694 var bkarray = bkups._vector.getArray(); 695 // Make checkbox behave like radio button 696 for (var k=0; k<bkarray.length; k++) { 697 if(bkarray[k].active && (bkarray[k].timestamp != z.timestamp)) { 698 var y = document.getElementById([bkarray[k].timestamp, "_", bkarray[k].acct, "_backupCheckbox"].join("")); 699 y.checked = false; 700 bkarray[k].active = false; 701 } 702 } 703 if (z) { 704 z.active = !z.active; 705 } 706 }; 707 708 ZmPrefBackupListView.prototype._allowLeftSelection = 709 function(clickedEl, ev, button) { 710 var target = DwtUiEvent.getTarget(ev); 711 var isInput = (target.id.indexOf("_backupCheckbox") > 0); 712 if (isInput) { 713 ZmPrefBackupListView._activeStateChange(ev); 714 } 715 716 return !isInput; 717 }; 718 719 720 /** 721 * Model class to hold the list of backups 722 * @private 723 */ 724 ZmPrefBackups = function() { 725 ZmModel.call(this, ZmEvent.S_PREF_BACKUP); 726 this._vector = new AjxVector(); 727 this._zNameHash = {}; 728 }; 729 730 ZmPrefBackups.prototype = new ZmModel; 731 ZmPrefBackups.prototype.constructor = ZmPrefBackups; 732 733 ZmPrefBackups.prototype.toString = 734 function() { 735 return "ZmPrefBackups"; 736 }; 737 738 ZmPrefBackups.prototype.addPrefBackup = 739 function(Backup) { 740 this._vector.add(Backup); 741 var hash = [Backup.timestamp, "_", Backup.acct].join(""); 742 this._zNameHash[hash] = Backup; 743 }; 744 745 ZmPrefBackups.prototype.removePrefBackup = 746 function(Backup) { 747 var hash = [Backup.timestamp, "_", Backup.acct].join(""); 748 delete this._zNameHash[hash]; 749 this._vector.remove(Backup); 750 }; 751 752 ZmPrefBackups.prototype.getPrefBackupByName = 753 function(hash) { 754 return this._zNameHash[hash]; 755 }; 756 757 /** 758 * ZmPrefBackup 759 * 760 * @param timestamp 761 * @param active 762 * @param fileSize 763 * @param acct 764 * 765 * @private 766 */ 767 ZmPrefBackup = function(timestamp, active, fileSize, acct) { 768 this.fileSize = fileSize; 769 this.active = (active !== false); 770 this.timestamp = timestamp; 771 this.acct = acct; 772 this._origStatus = this.active; 773 };