1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 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) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file contains the calendar application class. 27 */ 28 29 /** 30 * Creates and initializes the calendar application. 31 * @class 32 * The calendar application manages the creation and display of appointments. 33 * 34 * @param {DwtControl} container the container 35 * @param {ZmController} parentController the parent window controller (set by the child window) 36 * 37 * @author Conrad Damon 38 * 39 * @extends ZmApp 40 */ 41 ZmCalendarApp = function(container, parentController) { 42 43 ZmApp.call(this, ZmApp.CALENDAR, container, parentController); 44 45 this._addSettingsChangeListeners(); 46 47 // resource cache 48 this._resByName = {}; 49 this._resByEmail = {}; 50 }; 51 52 ZmCalendarApp.prototype = new ZmApp; 53 ZmCalendarApp.prototype.constructor = ZmCalendarApp; 54 55 ZmCalendarApp.prototype.isZmCalendarApp = true; 56 ZmCalendarApp.prototype.toString = function() { return "ZmCalendarApp"; }; 57 58 59 // Organizer and item-related constants 60 ZmEvent.S_APPT = ZmId.ITEM_APPOINTMENT; 61 ZmEvent.S_RESOURCE = ZmId.ITEM_RESOURCE; 62 ZmItem.APPT = ZmEvent.S_APPT; 63 ZmItem.RESOURCE = ZmEvent.S_RESOURCE; 64 /** 65 * Defines the "calendar" organizer. 66 */ 67 ZmOrganizer.CALENDAR = ZmId.ORG_CALENDAR; 68 69 // App-related constants 70 /** 71 * Defines the "calendar" application. 72 */ 73 ZmApp.CALENDAR = ZmId.APP_CALENDAR; 74 ZmApp.CLASS[ZmApp.CALENDAR] = "ZmCalendarApp"; 75 ZmApp.SETTING[ZmApp.CALENDAR] = ZmSetting.CALENDAR_ENABLED; 76 ZmApp.UPSELL_SETTING[ZmApp.CALENDAR] = ZmSetting.CALENDAR_UPSELL_ENABLED; 77 ZmApp.LOAD_SORT[ZmApp.CALENDAR] = 40; 78 ZmApp.QS_ARG[ZmApp.CALENDAR] = "calendar"; 79 80 // ms to wait before fetching reminders 81 ZmCalendarApp.REMINDER_START_DELAY = 10000; 82 ZmCalendarApp.MINICAL_DELAY = 5000; 83 84 ZmCalendarApp.VIEW_FOR_SETTING = {}; 85 ZmCalendarApp.VIEW_FOR_SETTING[ZmSetting.CAL_DAY] = ZmId.VIEW_CAL_DAY; 86 ZmCalendarApp.VIEW_FOR_SETTING[ZmSetting.CAL_WEEK] = ZmId.VIEW_CAL_WEEK; 87 ZmCalendarApp.VIEW_FOR_SETTING[ZmSetting.CAL_WORK_WEEK] = ZmId.VIEW_CAL_WORK_WEEK; 88 ZmCalendarApp.VIEW_FOR_SETTING[ZmSetting.CAL_MONTH] = ZmId.VIEW_CAL_MONTH; 89 ZmCalendarApp.VIEW_FOR_SETTING[ZmSetting.CAL_LIST] = ZmId.VIEW_CAL_LIST; 90 91 ZmCalendarApp.COLORS = []; 92 // these need to match CSS rules 93 ZmCalendarApp.COLORS[ZmOrganizer.C_ORANGE] = "Orange"; 94 ZmCalendarApp.COLORS[ZmOrganizer.C_BLUE] = "Blue"; 95 ZmCalendarApp.COLORS[ZmOrganizer.C_CYAN] = "Cyan"; 96 ZmCalendarApp.COLORS[ZmOrganizer.C_GREEN] = "Green"; 97 ZmCalendarApp.COLORS[ZmOrganizer.C_PURPLE] = "Purple"; 98 ZmCalendarApp.COLORS[ZmOrganizer.C_RED] = "Red"; 99 ZmCalendarApp.COLORS[ZmOrganizer.C_YELLOW] = "Yellow"; 100 ZmCalendarApp.COLORS[ZmOrganizer.C_PINK] = "Pink"; 101 ZmCalendarApp.COLORS[ZmOrganizer.C_GRAY] = "Gray"; 102 103 ZmCalendarApp.CUTYPE_INDIVIDUAL = "IND"; 104 ZmCalendarApp.CUTYPE_GROUP = "GRO"; 105 ZmCalendarApp.CUTYPE_RESOURCE = "RES"; 106 ZmCalendarApp.CUTYPE_ROOM = "ROO"; 107 ZmCalendarApp.CUTYPE_UNKNOWN = "UNK"; 108 109 ZmCalendarApp.STATUS_CANC = "CANC"; // vevent, vtodo 110 ZmCalendarApp.STATUS_COMP = "COMP"; // vtodo 111 ZmCalendarApp.STATUS_CONF = "CONF"; // vevent 112 ZmCalendarApp.STATUS_DEFR = "DEFERRED"; // vtodo [outlook] 113 ZmCalendarApp.STATUS_INPR = "INPR"; // vtodo 114 ZmCalendarApp.STATUS_NEED = "NEED"; // vtodo 115 ZmCalendarApp.STATUS_TENT = "TENT"; // vevent 116 ZmCalendarApp.STATUS_WAIT = "WAITING"; // vtodo [outlook] 117 118 ZmCalendarApp.METHOD_CANCEL = "CANCEL"; 119 ZmCalendarApp.METHOD_PUBLISH = "PUBLISH"; 120 ZmCalendarApp.METHOD_REPLY = "REPLY"; 121 ZmCalendarApp.METHOD_REQUEST = "REQUEST"; 122 ZmCalendarApp.METHOD_COUNTER = "COUNTER"; 123 124 ZmCalendarApp.DEFAULT_WORKING_HOURS = "1:N:0800:1700,2:Y:0800:1700,3:Y:0800:1700,4:Y:0800:1700,5:Y:0800:1700,6:Y:0800:1700,7:N:0800:1700"; 125 ZmCalendarApp.DEFAULT_APPT_DURATION = "60"; //60minutes 126 127 ZmCalendarApp.reminderTimeWarningDisplayMsgs = [ 128 ZmMsg.apptRemindNever, 129 ZmMsg.apptRemindAtEventTime, 130 ZmMsg.apptRemindNMinutesBefore, 131 ZmMsg.apptRemindNMinutesBefore, 132 ZmMsg.apptRemindNMinutesBefore, 133 ZmMsg.apptRemindNMinutesBefore, 134 ZmMsg.apptRemindNMinutesBefore, 135 ZmMsg.apptRemindNMinutesBefore, 136 ZmMsg.apptRemindNMinutesBefore, 137 ZmMsg.apptRemindNHoursBefore, 138 ZmMsg.apptRemindNHoursBefore, 139 ZmMsg.apptRemindNHoursBefore, 140 ZmMsg.apptRemindNHoursBefore, 141 ZmMsg.apptRemindNHoursBefore, 142 ZmMsg.apptRemindNDaysBefore, 143 ZmMsg.apptRemindNDaysBefore, 144 ZmMsg.apptRemindNDaysBefore, 145 ZmMsg.apptRemindNDaysBefore, 146 ZmMsg.apptRemindNWeeksBefore, 147 ZmMsg.apptRemindNWeeksBefore 148 ]; 149 150 ZmCalendarApp.reminderTimeWarningValues = [-1, 0, 1, 5, 10, 15, 30, 45, 60, 120, 180, 240, 300, 1080, 1440, 2880, 4320, 5760, 10080, 20160]; 151 ZmCalendarApp.reminderTimeWarningLabels = [-1, 0, 1, 5, 10, 15, 30, 45, 60, 2, 3, 4, 5, 18, 1, 2, 3, 4, 1, 2]; 152 153 // Construction 154 155 ZmCalendarApp.prototype._defineAPI = 156 function() { 157 AjxDispatcher.setPackageLoadFunction("CalendarCore", new AjxCallback(this, this._postLoadCore)); 158 AjxDispatcher.setPackageLoadFunction("Calendar", new AjxCallback(this, this._postLoad, ZmOrganizer.CALENDAR)); 159 AjxDispatcher.registerMethod("GetCalController", ["MailCore","CalendarCore"], new AjxCallback(this, this.getCalController)); 160 AjxDispatcher.registerMethod("GetReminderController", ["MailCore","CalendarCore"], new AjxCallback(this, this.getReminderController)); 161 AjxDispatcher.registerMethod("ShowMiniCalendar", ["MailCore","CalendarCore"], new AjxCallback(this, this.showMiniCalendar)); 162 AjxDispatcher.registerMethod("GetApptComposeController", ["MailCore","CalendarCore", "Calendar", "CalendarAppt"], new AjxCallback(this, this.getApptComposeController)); 163 }; 164 165 ZmCalendarApp.prototype._registerSettings = 166 function(settings) { 167 var settings = settings || appCtxt.getSettings(); 168 settings.registerSetting("CAL_ALWAYS_SHOW_MINI_CAL", {name: "zimbraPrefCalendarAlwaysShowMiniCal", type: ZmSetting.T_PREF, dataType: ZmSetting.D_BOOLEAN, defaultValue: false, isGlobal:true}); 169 settings.registerSetting("CAL_APPT_VISIBILITY", {name: "zimbraPrefCalendarApptVisibility", type: ZmSetting.T_PREF, dataType: ZmSetting.D_STRING, defaultValue: "public", isGlobal:true}); 170 settings.registerSetting("CAL_EMAIL_REMINDERS_ADDRESS", {name: "zimbraPrefCalendarReminderEmail", type:ZmSetting.T_PREF}); 171 settings.registerSetting("CAL_DEVICE_EMAIL_REMINDERS_ADDRESS", {name: "zimbraCalendarReminderDeviceEmail", type:ZmSetting.T_PREF}); 172 settings.registerSetting("CAL_DEVICE_EMAIL_REMINDERS_ENABLED", {name: "zimbraFeatureCalendarReminderDeviceEmailEnabled", type:ZmSetting.T_COS, dataType:ZmSetting.D_BOOLEAN, defaultValue:false}); 173 settings.registerSetting("CAL_EXPORT", {type: ZmSetting.T_PREF, dataType: ZmSetting.D_NONE}); 174 settings.registerSetting("CAL_FIRST_DAY_OF_WEEK", {name: "zimbraPrefCalendarFirstDayOfWeek", type: ZmSetting.T_PREF, dataType: ZmSetting.D_INT, defaultValue: 0, isGlobal:true}); 175 settings.registerSetting("CAL_FREE_BUSY_ACL", {type: ZmSetting.T_PREF, defaultValue:ZmSetting.ACL_ALL}); 176 settings.registerSetting("CAL_FREE_BUSY_ACL_USERS", {type: ZmSetting.T_PREF}); 177 settings.registerSetting("CAL_IMPORT", {type: ZmSetting.T_PREF, dataType: ZmSetting.D_NONE}); 178 settings.registerSetting("CAL_INVITE_ACL", {type: ZmSetting.T_PREF, defaultValue:ZmSetting.ACL_ALL}); 179 settings.registerSetting("CAL_INVITE_ACL_USERS", {type: ZmSetting.T_PREF}); 180 settings.registerSetting("CAL_REMINDER_NOTIFY_SOUNDS", {name: "zimbraPrefCalendarReminderSoundsEnabled", type:ZmSetting.T_PREF, dataType:ZmSetting.D_BOOLEAN, defaultValue:true, isGlobal:true}); 181 settings.registerSetting("CAL_REMINDER_NOTIFY_BROWSER", {name: "zimbraPrefCalendarReminderFlashTitle", type:ZmSetting.T_PREF, dataType:ZmSetting.D_BOOLEAN, defaultValue:true, isGlobal:true}); 182 settings.registerSetting("CAL_REMINDER_NOTIFY_TOASTER", {name: "zimbraPrefCalendarToasterEnabled", type:ZmSetting.T_PREF, dataType:ZmSetting.D_BOOLEAN, defaultValue:false, isGlobal:true}); 183 settings.registerSetting("CAL_REMINDER_WARNING_TIME", {name: "zimbraPrefCalendarApptReminderWarningTime", type: ZmSetting.T_PREF, dataType: ZmSetting.D_INT, defaultValue: 0, isGlobal:true}); 184 settings.registerSetting("CAL_SHOW_DECLINED_MEETINGS", {name: "zimbraPrefCalendarShowDeclinedMeetings", type: ZmSetting.T_PREF,dataType:ZmSetting.D_BOOLEAN, defaultValue:true}); 185 settings.registerSetting("CAL_SHOW_TIMEZONE", {name: "zimbraPrefUseTimeZoneListInCalendar", type: ZmSetting.T_PREF, dataType: ZmSetting.D_BOOLEAN, defaultValue: false, isGlobal:true}); 186 settings.registerSetting("CAL_USE_QUICK_ADD", {name: "zimbraPrefCalendarUseQuickAdd", type: ZmSetting.T_PREF, dataType: ZmSetting.D_BOOLEAN, defaultValue: true, isGlobal:true}); 187 settings.registerSetting("CALENDAR_INITIAL_VIEW", {name: "zimbraPrefCalendarInitialView", type: ZmSetting.T_PREF, defaultValue: ZmSetting.CAL_DAY, isGlobal:true}); 188 settings.registerSetting("CAL_WORKING_HOURS", {name: "zimbraPrefCalendarWorkingHours", type: ZmSetting.T_PREF, defaultValue: ZmCalendarApp.DEFAULT_WORKING_HOURS, isGlobal:true}); 189 settings.registerSetting("FREE_BUSY_VIEW_ENABLED", {name: "zimbraFeatureFreeBusyViewEnabled", type:ZmSetting.T_COS, dataType: ZmSetting.D_BOOLEAN, defaultValue:false}); 190 settings.registerSetting("DELETE_INVITE_ON_REPLY", {name: "zimbraPrefDeleteInviteOnReply",type: ZmSetting.T_PREF, dataType: ZmSetting.D_BOOLEAN, defaultValue: true, isGlobal:true}); 191 settings.registerSetting("ENABLE_APPL_ICAL_DELEGATION", {name: "zimbraPrefAppleIcalDelegationEnabled",type: ZmSetting.T_PREF, dataType: ZmSetting.D_BOOLEAN, defaultValue: false, isGlobal:true}); 192 settings.registerSetting("CAL_AUTO_ADD_INVITES", {name: "zimbraPrefCalendarAutoAddInvites",type: ZmSetting.T_PREF, dataType: ZmSetting.D_BOOLEAN, defaultValue: true}); 193 settings.registerSetting("CAL_SEND_INV_DENIED_REPLY", {name: "zimbraPrefCalendarSendInviteDeniedAutoReply",type: ZmSetting.T_PREF, dataType: ZmSetting.D_BOOLEAN, defaultValue: false}); 194 settings.registerSetting("CAL_INV_FORWARDING_ADDRESS", {name: "zimbraPrefCalendarForwardInvitesTo", type:ZmSetting.T_PREF, dataType:ZmSetting.D_LIST, isGlobal:true}); 195 settings.registerSetting("CAL_SHOW_PAST_DUE_REMINDERS", {name: "zimbraPrefCalendarShowPastDueReminders", type:ZmSetting.T_PREF, dataType:ZmSetting.D_BOOLEAN, defaultValue: true, isGlobal:true}); 196 settings.registerSetting("CAL_SHOW_CALENDAR_WEEK", {name: "zimbraPrefShowCalendarWeek", type:ZmSetting.T_PREF, dataType:ZmSetting.D_BOOLEAN, defaultValue: false, isGlobal:true}); 197 settings.registerSetting("CAL_APPT_ALLOW_ATTENDEE_EDIT", {name: "zimbraPrefCalendarApptAllowAtendeeEdit", type:ZmSetting.T_PREF, dataType:ZmSetting.D_BOOLEAN, defaultValue: true, isGlobal:true}); 198 settings.registerSetting("CAL_RESOURCE_DBL_BOOKING_ALLOWED", {name: "zimbraCalendarResourceDoubleBookingAllowed", type:ZmSetting.T_COS, dataType:ZmSetting.D_BOOLEAN, defaultValue: true, isGlobal:true}); 199 settings.registerSetting("CAL_SHOW_RESOURCE_TABS", {name: "zimbraCalendarShowResourceTabs", type:ZmSetting.T_PREF, dataType:ZmSetting.D_BOOLEAN, defaultValue: true, isGlobal:true}); 200 settings.registerSetting("CAL_DEFAULT_APPT_DURATION", {name: "zimbraPrefCalendarDefaultApptDuration", type:ZmSetting.T_PREF, dataType:ZmSetting.D_LDAP_TIME, defaultValue:ZmCalendarApp.DEFAULT_APPT_DURATION, isGlobal:true}); 201 settings.registerSetting("CAL_EXCEPTION_ON_SERIES_TIME_CHANGE", {name: "zimbraCalendarKeepExceptionsOnSeriesTimeChange", type:ZmSetting.T_COS, dataType:ZmSetting.D_BOOLEAN, defaultValue: false, isGlobal:true}); 202 settings.registerSetting("CAL_LOCATION_FIELDS_DISABLED",{name: "zimbraCalendarLocationDisabledFields", type: ZmSetting.T_COS, dataType: ZmSetting.D_STRING, defaultValue: false, isGlobal:true}); 203 }; 204 205 ZmCalendarApp.prototype._registerPrefs = 206 function() { 207 var sections = { 208 CALENDAR: { 209 title: ZmMsg.calendar, 210 icon: "CalendarApp", 211 templateId: "prefs.Pages#Calendar", 212 priority: 80, 213 precondition: ZmSetting.CALENDAR_ENABLED, 214 prefs: [ 215 ZmSetting.CAL_ALWAYS_SHOW_MINI_CAL, 216 ZmSetting.CAL_AUTO_ADD_INVITES, 217 ZmSetting.CAL_SEND_INV_DENIED_REPLY, 218 ZmSetting.CAL_APPT_VISIBILITY, 219 ZmSetting.CAL_EXPORT, 220 ZmSetting.CAL_FIRST_DAY_OF_WEEK, 221 ZmSetting.CAL_IMPORT, 222 ZmSetting.CAL_REMINDER_WARNING_TIME, 223 ZmSetting.CAL_REMINDER_NOTIFY_SOUNDS, 224 ZmSetting.CAL_REMINDER_NOTIFY_BROWSER, 225 ZmSetting.CAL_SHOW_DECLINED_MEETINGS, 226 ZmSetting.CAL_SHOW_TIMEZONE, 227 ZmSetting.CAL_USE_QUICK_ADD, 228 ZmSetting.CALENDAR_INITIAL_VIEW, 229 ZmSetting.CAL_WORKING_HOURS, 230 ZmSetting.DELETE_INVITE_ON_REPLY, 231 ZmSetting.ENABLE_APPL_ICAL_DELEGATION, 232 ZmSetting.CAL_FREE_BUSY_ACL, 233 ZmSetting.CAL_FREE_BUSY_ACL_USERS, 234 ZmSetting.CAL_INVITE_ACL, 235 ZmSetting.CAL_INVITE_ACL_USERS, 236 ZmSetting.CAL_REMINDER_NOTIFY_TOASTER, 237 ZmSetting.CAL_INV_FORWARDING_ADDRESS, 238 ZmSetting.CAL_SHOW_PAST_DUE_REMINDERS, 239 ZmSetting.CAL_SHOW_CALENDAR_WEEK, 240 ZmSetting.CAL_DEFAULT_APPT_DURATION, 241 ZmSetting.CAL_LOCATION_FIELDS_DISABLED 242 ], 243 manageDirty: true, 244 createView: function(parent, section, controller) { 245 AjxDispatcher.require("Alert"); 246 return new ZmCalendarPrefsPage(parent, section, controller); 247 } 248 } 249 }; 250 251 for (var id in sections) { 252 ZmPref.registerPrefSection(id, sections[id]); 253 } 254 255 ZmPref.registerPref("CAL_ALWAYS_SHOW_MINI_CAL", { 256 displayName: ZmMsg.alwaysShowMiniCal, 257 displayContainer: ZmPref.TYPE_CHECKBOX 258 }); 259 260 ZmPref.registerPref("CAL_WORKING_HOURS", { 261 displayContainer: ZmPref.TYPE_CUSTOM 262 }); 263 264 ZmPref.registerPref("CAL_AUTO_ADD_INVITES", { 265 displayName: ZmMsg.autoAddInvites, 266 displayContainer: ZmPref.TYPE_CHECKBOX 267 }); 268 269 ZmPref.registerPref("CAL_SEND_INV_DENIED_REPLY", { 270 displayName: ZmMsg.sendInvDeniedAutoReply, 271 displayContainer: ZmPref.TYPE_CHECKBOX 272 }); 273 274 ZmPref.registerPref("CAL_EMAIL_REMINDERS_ADDRESS", { 275 displayName: ZmMsg.emailNotificationsDescription, 276 displayContainer: ZmPref.TYPE_INPUT, 277 // validationFunction: ZmMailApp.validateForwardEmail, 278 errorMessage: ZmMsg.invalidEmail, 279 hint: ZmMsg.enterEmailAddress 280 }); 281 282 ZmPref.registerPref("CAL_DEVICE_EMAIL_REMINDERS_ADDRESS", { 283 displayName: ZmMsg.deviceEmailNotificationsDescription, 284 displayContainer: ZmPref.TYPE_INPUT, 285 // validationFunction: ZmMailApp.validateForwardEmail, 286 errorMessage: ZmMsg.invalidEmail, 287 hint: ZmMsg.enterEmailAddress 288 }); 289 290 ZmPref.registerPref("CAL_EXPORT", { 291 displayName: ZmMsg.exportToICS, 292 displayContainer: ZmPref.TYPE_EXPORT 293 }); 294 295 ZmPref.registerPref("CAL_FIRST_DAY_OF_WEEK", { 296 displayName: ZmMsg.calendarFirstDayOfWeek, 297 displayContainer: ZmPref.TYPE_SELECT, 298 displayOptions: AjxDateUtil.WEEKDAY_LONG, 299 options: [0,1,2,3,4,5,6] 300 }); 301 302 ZmPref.registerPref("CAL_FREE_BUSY_ACL", { 303 displayContainer: ZmPref.TYPE_RADIO_GROUP, 304 displayOptions: [ZmMsg.freeBusyAllowAll, ZmMsg.freeBusyAllowLocal, ZmMsg.freeBusyAllowDomain, ZmMsg.freeBusyAllowNone, ZmMsg.freeBusyAllowSome], 305 options: [ZmSetting.ACL_PUBLIC, ZmSetting.ACL_AUTH, ZmSetting.ACL_DOMAIN, ZmSetting.ACL_NONE, ZmSetting.ACL_USER] 306 }); 307 308 ZmPref.registerPref("CAL_FREE_BUSY_ACL_USERS", { 309 displayContainer: ZmPref.TYPE_TEXTAREA, 310 hint: ZmMsg.enterEmailAddresses 311 }); 312 313 ZmPref.registerPref("CAL_IMPORT", { 314 displayName: ZmMsg.importFromICS, 315 displayContainer: ZmPref.TYPE_IMPORT 316 }); 317 318 ZmPref.registerPref("CAL_INVITE_ACL", { 319 displayContainer: ZmPref.TYPE_RADIO_GROUP, 320 displayOptions: [ZmMsg.invitesAllowAll, ZmMsg.invitesAllowLocal, ZmMsg.invitesAllowNone, ZmMsg.invitesAllowSome], 321 options: [ZmSetting.ACL_PUBLIC, ZmSetting.ACL_AUTH, ZmSetting.ACL_NONE, ZmSetting.ACL_USER] 322 }); 323 324 ZmPref.registerPref("CAL_INVITE_ACL_USERS", { 325 displayContainer: ZmPref.TYPE_TEXTAREA, 326 hint: ZmMsg.enterEmailAddresses 327 }); 328 329 ZmPref.registerPref("CAL_REMINDER_WARNING_TIME", { 330 displayName: ZmMsg.numberOfMinutes, 331 displayContainer: ZmPref.TYPE_SELECT, 332 displayOptions: ZmCalendarApp.getReminderTimeWarningDisplayOptions(), 333 options: ZmCalendarApp.reminderTimeWarningValues, 334 setFunction: ZmCalendarApp.setDefaultReminderTimePrefValueOnSave, 335 loadFunction: ZmCalendarApp.postLoadSetDefaultReminderValue 336 }); 337 338 ZmPref.registerPref("CAL_SHOW_DECLINED_MEETINGS", { 339 displayName: ZmMsg.showDeclinedMeetings, 340 displayContainer: ZmPref.TYPE_CHECKBOX 341 }); 342 343 ZmPref.registerPref("CAL_SHOW_TIMEZONE", { 344 displayName: ZmMsg.shouldShowTimezone, 345 displayContainer: ZmPref.TYPE_CHECKBOX 346 }); 347 348 ZmPref.registerPref("CAL_USE_QUICK_ADD", { 349 displayName: ZmMsg.useQuickAdd, 350 displayContainer: ZmPref.TYPE_CHECKBOX 351 }); 352 353 ZmPref.registerPref("CALENDAR_INITIAL_VIEW", { 354 displayName: ZmMsg.calendarInitialView, 355 displayContainer: ZmPref.TYPE_SELECT, 356 displayOptions: [ZmMsg.calViewDay, ZmMsg.calViewWorkWeek, ZmMsg.calViewWeek, ZmMsg.calViewMonth, ZmMsg.calViewList], 357 options: [ZmSetting.CAL_DAY, ZmSetting.CAL_WORK_WEEK, ZmSetting.CAL_WEEK, ZmSetting.CAL_MONTH, ZmSetting.CAL_LIST] 358 }); 359 360 ZmPref.registerPref("CAL_REMINDER_NOTIFY_SOUNDS", { 361 displayName: ZmMsg.playSound, 362 displayContainer: ZmPref.TYPE_CHECKBOX 363 }); 364 365 ZmPref.registerPref("CAL_REMINDER_NOTIFY_BROWSER", { 366 displayName: ZmMsg.flashBrowser, 367 displayContainer: ZmPref.TYPE_CHECKBOX 368 }); 369 370 ZmPref.registerPref("DELETE_INVITE_ON_REPLY", { 371 displayName: ZmMsg.deleteInviteOnReply, 372 displayContainer: ZmPref.TYPE_CHECKBOX 373 }); 374 375 ZmPref.registerPref("ENABLE_APPL_ICAL_DELEGATION", { 376 displayName: ZmMsg.enableAppleICalDelegation, 377 displayContainer: ZmPref.TYPE_CHECKBOX 378 }); 379 380 AjxDispatcher.require("Alert"); 381 var notifyText = ZmDesktopAlert.getInstance().getDisplayText(); 382 ZmPref.registerPref("CAL_REMINDER_NOTIFY_TOASTER", { 383 displayFunc: function() { return notifyText; }, 384 precondition: !!notifyText, 385 displayContainer: ZmPref.TYPE_CHECKBOX 386 }); 387 388 ZmPref.registerPref("CAL_APPT_VISIBILITY", { 389 displayName: ZmMsg.calendarInitialApptVisibility, 390 displayContainer: ZmPref.TYPE_SELECT, 391 displayOptions: [ZmMsg._public, ZmMsg._private], 392 options: [ZmSetting.CAL_VISIBILITY_PUB, ZmSetting.CAL_VISIBILITY_PRIV] 393 }); 394 395 ZmPref.registerPref("CAL_INV_FORWARDING_ADDRESS", { 396 displayName: ZmMsg.inviteForwardingAddress, 397 displayContainer: ZmPref.TYPE_INPUT, 398 validationFunction: ZmPref.validateEmailList, 399 valueFunction: ZmPref.string2EmailList, 400 errorMessage: ZmMsg.invalidEmail, 401 hint: ZmMsg.enterEmailAddress 402 }); 403 404 ZmPref.registerPref("CAL_SHOW_PAST_DUE_REMINDERS", { 405 displayName: ZmMsg.apptPastDueReminderLabel, 406 displayContainer: ZmPref.TYPE_CHECKBOX 407 }); 408 409 ZmPref.registerPref("CAL_SHOW_CALENDAR_WEEK", { 410 displayName: ZmMsg.showWeekNumber, 411 displayContainer: ZmPref.TYPE_CHECKBOX 412 }); 413 414 ZmPref.registerPref("CAL_DEFAULT_APPT_DURATION", { 415 displayName: ZmMsg.defaultApptDuration, 416 displayContainer: ZmPref.TYPE_SELECT, 417 displayOptions: ["30","60","90","120"], 418 options: ["1800", "3600", "5400", "7200"] 419 }); 420 }; 421 422 ZmCalendarApp.prototype._registerOperations = 423 function() { 424 ZmOperation.registerOp(ZmId.OP_CAL_LIST_VIEW, {textKey:"list", tooltipKey:"viewCalListTooltip", image:"CalListView", shortcut:ZmKeyMap.CAL_LIST_VIEW}); 425 ZmOperation.registerOp(ZmId.OP_CAL_REFRESH, {textKey:"refresh", tooltipKey:"calRefreshTooltip", image:"Refresh", shortcut:ZmKeyMap.REFRESH, showImageInToolbar: true}); 426 ZmOperation.registerOp(ZmId.OP_CAL_VIEW_MENU, {textKey:"view", image:"Appointment"}, null, 427 AjxCallback.simpleClosure(function(parent) { 428 ZmOperation.addDeferredMenu(ZmCalendarApp.addCalViewMenu, parent); 429 })); 430 ZmOperation.registerOp(ZmId.OP_DAY_VIEW, {textKey:"viewDay", tooltipKey:"viewDayTooltip", image:"DayView", shortcut:ZmKeyMap.CAL_DAY_VIEW}); 431 ZmOperation.registerOp(ZmId.OP_EDIT_REPLY_ACCEPT, {textKey:"replyAccept", image:"Check"}); 432 ZmOperation.registerOp(ZmId.OP_EDIT_REPLY_CANCEL); 433 ZmOperation.registerOp(ZmId.OP_EDIT_REPLY_TENTATIVE, {textKey:"replyTentative", image:"QuestionMark"}); 434 ZmOperation.registerOp(ZmId.OP_EDIT_REPLY_DECLINE, {textKey:"replyDecline", image:"Cancel"}); 435 ZmOperation.registerOp(ZmId.OP_INVITE_REPLY_ACCEPT, {textKey:"editReply", image:"Check"}); 436 ZmOperation.registerOp(ZmId.OP_INVITE_REPLY_DECLINE, {textKey:"editReply", image:"Cancel"}); 437 ZmOperation.registerOp(ZmId.OP_INVITE_REPLY_MENU, {textKey:"editReply", image:"Reply"}, ZmSetting.MAIL_ENABLED, 438 AjxCallback.simpleClosure(function(parent) { 439 ZmOperation.addDeferredMenu(ZmCalendarApp.addInviteReplyMenu, parent); 440 })); 441 ZmOperation.registerOp(ZmId.OP_INVITE_REPLY_TENTATIVE, {textKey:"editReply", image:"QuestionMark"}); 442 ZmOperation.registerOp(ZmId.OP_MONTH_VIEW, {textKey:"viewMonth", tooltipKey:"viewMonthTooltip", image:"MonthView", shortcut:ZmKeyMap.CAL_MONTH_VIEW}); 443 ZmOperation.registerOp(ZmId.OP_MOUNT_CALENDAR, {textKey:"mountCalendar", image:"GroupSchedule"}); 444 ZmOperation.registerOp(ZmId.OP_NEW_ALLDAY_APPT, {textKey:"newAllDayAppt", tooltipKey:"newAllDayApptTooltip", image:"NewAppointment"}); 445 ZmOperation.registerOp(ZmId.OP_NEW_APPT, {textKey:"newAppt", tooltipKey:"newApptTooltip", image:"NewAppointment", shortcut:ZmKeyMap.NEW_APPT}); 446 ZmOperation.registerOp(ZmId.OP_NEW_CALENDAR, {textKey:"newCalendar", image:"NewAppointment", tooltipKey: "newCalendarTooltip", shortcut:ZmKeyMap.NEW_CALENDAR}); 447 ZmOperation.registerOp(ZmId.OP_ADD_EXTERNAL_CALENDAR, {textKey:"addExternalCalendar", image:"NewAppointment", tooltipKey: "addExternalCalendarTooltip", shortcut:ZmKeyMap.ADD_EXTERNAL_CALENDAR}); 448 ZmOperation.registerOp(ZmId.OP_PRINT_CALENDAR, {textKey:"print", tooltipKey:"printTooltip", image:"Print", shortcut:ZmKeyMap.PRINT, textPrecedence:30, showImageInToolbar: true}, ZmSetting.PRINT_ENABLED); 449 ZmOperation.registerOp(ZmId.OP_PROPOSE_NEW_TIME, {textKey:"proposeNewTime", image:"ProposeTime", showTextInToolbar: true, showImageInToolbar: true}); 450 ZmOperation.registerOp(ZmId.OP_REINVITE_ATTENDEES, {textKey:"reinviteAttendees", image:"MeetingRequest"}); 451 ZmOperation.registerOp(ZmId.OP_FB_VIEW, {textKey:"viewFB", tooltipKey:"viewFBTooltip", image:"GroupSchedule", shortcut:ZmKeyMap.CAL_FB_VIEW}); 452 ZmOperation.registerOp(ZmId.OP_SEARCH_MAIL, {textKey:"searchMail", image:"SearchMail"}, ZmSetting.MAIL_ENABLED); 453 ZmOperation.registerOp(ZmId.OP_SHARE_CALENDAR, {textKey:"shareCalendar", image:"CalendarFolder"}); 454 ZmOperation.registerOp(ZmId.OP_TODAY, {textKey:"today", tooltipKey:"todayTooltip", image:"Date", shortcut:ZmKeyMap.TODAY}); 455 ZmOperation.registerOp(ZmId.OP_VIEW_APPOINTMENT, {textKey:"viewAppointment", image:"Appointment"}); 456 ZmOperation.registerOp(ZmId.OP_OPEN_APPT_INSTANCE, {textKey:"openApptInstance", image:"Appointment"}); 457 ZmOperation.registerOp(ZmId.OP_OPEN_APPT_SERIES, {textKey:"openApptSeries", image:"Appointment"}); 458 ZmOperation.registerOp(ZmId.OP_DELETE_APPT_INSTANCE, {textKey:"deleteApptInstance", image:"Delete"}); 459 ZmOperation.registerOp(ZmId.OP_DELETE_APPT_SERIES, {textKey:"deleteApptSeries", image:"Delete"}); 460 ZmOperation.registerOp(ZmId.OP_VIEW_APPT_INSTANCE, {textKey:"apptInstance", image:"Appointment"}); 461 ZmOperation.registerOp(ZmId.OP_VIEW_APPT_SERIES, {textKey:"apptSeries", image:"Appointment"}); 462 ZmOperation.registerOp(ZmId.OP_WEEK_VIEW, {textKey:"viewWeek", tooltipKey:"viewWeekTooltip", image:"WeekView", shortcut:ZmKeyMap.CAL_WEEK_VIEW}); 463 ZmOperation.registerOp(ZmId.OP_WORK_WEEK_VIEW, {textKey:"viewWorkWeek", tooltipKey:"viewWorkWeekTooltip", image:"WorkWeekView", shortcut:ZmKeyMap.CAL_WORK_WEEK_VIEW}); 464 ZmOperation.registerOp(ZmId.OP_FORWARD_APPT, {textKey:"forward", tooltipKey:"forward", image:"Forward"}); 465 ZmOperation.registerOp(ZmId.OP_FORWARD_APPT_INSTANCE, {textKey:"forwardInstance", tooltipKey:"forwardInstance", image:"Forward"}); 466 ZmOperation.registerOp(ZmId.OP_FORWARD_APPT_SERIES, {textKey:"forwardSeries", tooltipKey:"forwardSeries", image:"Forward"}); 467 ZmOperation.registerOp(ZmId.OP_DUPLICATE_APPT, {textKey:"createCopy", tooltipKey:"createCopy", image:"Copy"}); 468 ZmOperation.registerOp(ZmId.OP_INVITE_ATTENDEES, {textKey:"inviteAttendees", tooltipKey:"inviteAttendees", image:"Group"}); 469 ZmOperation.registerOp(ZmId.OP_SEND_INVITE, {textKey:"send", tooltipKey:"sendInvites", image:"MeetingRequest"}); 470 }; 471 472 ZmCalendarApp.prototype._registerItems = 473 function() { 474 ZmItem.registerItem(ZmItem.APPT, 475 {app: ZmApp.CALENDAR, 476 nameKey: "appointment", 477 icon: "Appointment", 478 soapCmd: "ItemAction", 479 itemClass: "ZmAppt", 480 node: "appt", 481 organizer: ZmOrganizer.CALENDAR, 482 dropTargets: [ZmOrganizer.TAG, ZmOrganizer.CALENDAR], 483 searchType: "appointment", 484 resultsList: 485 AjxCallback.simpleClosure(function(search) { 486 AjxDispatcher.require(["MailCore", "CalendarCore"]); 487 return new ZmApptList(ZmItem.APPT, search); 488 }, this) 489 }); 490 491 ZmItem.registerItem(ZmItem.RESOURCE, 492 {app: ZmApp.CALENDAR, 493 itemClass: "ZmResource", 494 node: "calResource", 495 resultsList: 496 AjxCallback.simpleClosure(function(search) { 497 AjxDispatcher.require(["MailCore", "CalendarCore"]); 498 return new ZmResourceList(null, search); 499 }, this) 500 }); 501 }; 502 503 ZmCalendarApp.prototype._registerOrganizers = 504 function() { 505 ZmOrganizer.registerOrg(ZmOrganizer.CALENDAR, 506 {app: ZmApp.CALENDAR, 507 nameKey: "calendar", 508 defaultFolder: ZmOrganizer.ID_CALENDAR, 509 soapCmd: "FolderAction", 510 firstUserId: 256, 511 orgClass: "ZmCalendar", 512 orgPackage: "CalendarCore", 513 treeController: "ZmCalendarTreeController", 514 labelKey: "calendars", 515 itemsKey: "appointments", 516 hasColor: true, 517 defaultColor: ZmOrganizer.C_BLUE, 518 treeType: ZmOrganizer.FOLDER, 519 views: ["appointment"], 520 folderKey: "calendar", 521 mountKey: "mountCalendar", 522 createFunc: "ZmCalendar.create", 523 compareFunc: "ZmFolder.sortCompareNonMail", 524 newOp: ZmOperation.NEW_CALENDAR, 525 displayOrder: 100, 526 deferrable: true, 527 childWindow: true 528 }); 529 }; 530 531 ZmCalendarApp.prototype._setupSearchToolbar = 532 function() { 533 var params = { 534 msgKey: "appointments", 535 tooltipKey: "searchAppts", 536 icon: "Appointment", 537 shareIcon: "SharedCalendarFolder", 538 id: ZmId.getMenuItemId(ZmId.SEARCH, ZmId.ITEM_APPOINTMENT) 539 }; 540 // always enable appt search for offline 541 if(!appCtxt.isOffline) { 542 params["setting"] = ZmSetting.CALENDAR_ENABLED; 543 } 544 ZmSearchToolBar.addMenuItem(ZmItem.APPT, params); 545 }; 546 547 ZmCalendarApp.prototype._registerApp = 548 function() { 549 var newItemOps = {}; 550 newItemOps[ZmOperation.NEW_APPT] = "appointment"; 551 552 var newOrgOps = {}; 553 newOrgOps[ZmOperation.NEW_CALENDAR] = "calendar"; 554 555 var actionCodes = {}; 556 actionCodes[ZmKeyMap.NEW_APPT] = ZmOperation.NEW_APPT; 557 actionCodes[ZmKeyMap.NEW_CALENDAR] = ZmOperation.NEW_CALENDAR; 558 actionCodes[ZmKeyMap.ADD_EXTERNAL_CALENDAR] = ZmOperation.ADD_EXTERNAL_CALENDAR; 559 560 ZmApp.registerApp(ZmApp.CALENDAR, 561 {mainPkg: "Calendar", 562 nameKey: "calendar", 563 icon: "CalendarApp", 564 textPrecedence: 60, 565 chooserTooltipKey: "goToCalendar", 566 viewTooltipKey: "displayCalendar", 567 defaultSearch: ZmItem.APPT, 568 organizer: ZmOrganizer.CALENDAR, 569 overviewTrees: [ZmOrganizer.CALENDAR, ZmOrganizer.SEARCH, ZmOrganizer.TAG], 570 newItemOps: newItemOps, 571 newOrgOps: newOrgOps, 572 actionCodes: actionCodes, 573 searchTypes: [ZmItem.APPT], 574 gotoActionCode: ZmKeyMap.GOTO_CALENDAR, 575 newActionCode: ZmKeyMap.NEW_APPT, 576 chooserSort: 30, 577 defaultSort: 20, 578 upsellUrl: ZmSetting.CALENDAR_UPSELL_URL, 579 //quickCommandType: ZmQuickCommand[ZmId.ITEM_APPOINTMENT], 580 searchResultsTab: true 581 }); 582 }; 583 584 ZmCalendarApp.prototype._getRefreshButtonTooltip = 585 function() { 586 return ZmMsg.showAllEventsFromSelectedCalendars; 587 }; 588 589 // App API 590 591 ZmCalendarApp.prototype.startup = 592 function(result) { 593 }; 594 595 ZmCalendarApp.prototype.refresh = 596 function(refresh) { 597 if (!appCtxt.inStartup) { 598 this.resetOverview(this.getOverviewId()); 599 AjxDispatcher.run("GetCalController").refreshHandler(refresh); 600 } 601 }; 602 603 ZmCalendarApp.prototype.runRefresh = 604 function() { 605 appCtxt.getCalManager().getCalViewController().runRefresh(); 606 }; 607 608 609 ZmCalendarApp.prototype.deleteNotify = 610 function(ids, force) { 611 if (!force && this._deferNotifications("delete", ids)) { return; } 612 AjxDispatcher.run("GetCalController").notifyDelete(ids); 613 }; 614 615 /** 616 * Checks for the creation of a calendar or a mount point to one, or an 617 * appointment. 618 * 619 * @param {Hash} creates a hash of create notifications 620 * 621 * @private 622 */ 623 ZmCalendarApp.prototype.createNotify = 624 function(creates, force) { 625 if (!creates["folder"] && !creates["appt"] && !creates["link"]) { return; } 626 if (!force && !this._noDefer && this._deferNotifications("create", creates)) { return; } 627 628 var ctlr = AjxDispatcher.run("GetCalController"); 629 for (var name in creates) { 630 var list = creates[name]; 631 for (var i = 0; i < list.length; i++) { 632 var create = list[i]; 633 if (appCtxt.cacheGet(create.id)) { continue; } 634 635 if (name == "folder") { 636 this._handleCreateFolder(create, ZmOrganizer.CALENDAR); 637 } else if (name == "link") { 638 this._handleCreateLink(create, ZmOrganizer.CALENDAR); 639 } else if (name == "appt") { 640 ctlr.notifyCreate(create); 641 } 642 643 if ((name == "folder" || name == "link") && ctlr) { 644 ctlr._updateCheckedCalendars(); 645 } 646 } 647 } 648 }; 649 650 ZmCalendarApp.prototype.modifyNotify = 651 function(modifies, force) { 652 if (!force && !this._noDefer && this._deferNotifications("modify", modifies)) { return; } 653 AjxDispatcher.run("GetCalController").notifyModify(modifies); 654 }; 655 656 ZmCalendarApp.prototype.preNotify = 657 function(notify) { 658 var ctlr = AjxDispatcher.run("GetCalController"); 659 if (ctlr) { 660 ctlr.preNotify(notify); 661 } 662 }; 663 664 ZmCalendarApp.prototype.postNotify = 665 function(notify) { 666 var ctlr = AjxDispatcher.run("GetCalController"); 667 if (ctlr) { 668 ctlr.postNotify(notify); 669 } 670 }; 671 672 ZmCalendarApp.prototype.handleOp = 673 function(op) { 674 if (!appCtxt.isWebClientOffline()) { 675 switch (op) { 676 case ZmOperation.NEW_APPT: { 677 var loadCallback = new AjxCallback(this, this._handleLoadNewAppt); 678 AjxDispatcher.require(["MailCore", "CalendarCore", "Calendar"], false, loadCallback, null, true); 679 break; 680 } 681 case ZmOperation.NEW_CALENDAR: { 682 var loadCallback = new AjxCallback(this, this._handleLoadNewCalendar); 683 AjxDispatcher.require(["MailCore", "CalendarCore", "Calendar"], false, loadCallback, null, true); 684 break; 685 } 686 case ZmOperation.ADD_EXTERNAL_CALENDAR: { 687 var loadCallback = new AjxCallback(this, this._handleLoadExternalCalendar); 688 AjxDispatcher.require(["MailCore", "CalendarCore", "Calendar"], false, loadCallback, null, true); 689 break; 690 } 691 } 692 } 693 }; 694 695 ZmCalendarApp.prototype._handleLoadNewAppt = 696 function() { 697 Dwt.setLoadingTime("ZmCalendarApp-newAppt"); 698 AjxDispatcher.run("GetCalController").newAppointment(null, null, null, null); 699 Dwt.setLoadedTime("ZmCalendarApp-newAppt"); 700 }; 701 702 ZmCalendarApp.prototype._handleLoadNewCalendar = 703 function() { 704 appCtxt.getAppViewMgr().popView(true, ZmId.VIEW_LOADING); // pop "Loading..." page 705 var dialog = appCtxt.getNewCalendarDialog(); 706 if (!this._newCalendarCb) { 707 this._newCalendarCb = new AjxCallback(this, this._newCalendarCallback); 708 } 709 ZmController.showDialog(dialog, this._newCalendarCb); 710 }; 711 712 ZmCalendarApp.prototype._handleLoadExternalCalendar = 713 function() { 714 appCtxt.getAppViewMgr().popView(true, ZmId.VIEW_LOADING); 715 var oc = appCtxt.getOverviewController(); 716 var tc = oc.getTreeController(ZmOrganizer.CALENDAR); 717 if(tc) { 718 tc._addExternalCalendarListener(); 719 } 720 }; 721 722 // Public methods 723 724 ZmCalendarApp.prototype.launch = 725 function(params, callback) { 726 this._setLaunchTime(this.toString(), new Date()); 727 var loadCallback = new AjxCallback(this, this._handleLoadLaunch, [params, callback]); 728 AjxDispatcher.require(["MailCore", "ContactsCore", "CalendarCore", "Calendar"], true, loadCallback, null, true); 729 }; 730 731 ZmCalendarApp.prototype._handleLoadLaunch = 732 function(params, callback) { 733 var cc = AjxDispatcher.run("GetCalController"); 734 var view = cc.getDefaultViewType(); 735 var sd = null; 736 737 params = params || {}; 738 if (params.qsParams) { 739 var viewArg = params.qsParams.view; 740 if (viewArg) { 741 var viewId = ZmCalendarApp.VIEW_FOR_SETTING[viewArg]; 742 if (viewId) { 743 view = viewId; 744 var date = params.qsParams.date; 745 if (date) { 746 date = AjxDateUtil.parseServerDateTime(date); 747 if (date && !isNaN(date)) { 748 sd = new Date((date).setHours(0,0,0,0)); 749 } 750 } 751 } 752 } 753 } 754 755 if (appCtxt.get(ZmSetting.CONTACTS_ENABLED)) { 756 this.initResources(); 757 } 758 ZmCalendarApp.postLoadSetDefaultReminderValue(); 759 cc.show(view, sd); 760 this._setLoadedTime(this.toString(), new Date()); 761 if (callback) { 762 callback.run(); 763 } 764 this._setRefreshButtonTooltip(); 765 }; 766 767 ZmCalendarApp.prototype.getNewButtonProps = 768 function() { 769 return { 770 text: ZmMsg.newAppt, 771 tooltip: ZmMsg.createNewAppt, 772 icon: "NewAppointment", 773 iconDis: "NewAppointmentDis", 774 defaultId: ZmOperation.NEW_APPT, 775 disabled: !this.containsWritableFolder() 776 }; 777 }; 778 779 ZmCalendarApp.prototype.showSearchResults = 780 function(results, callback) { 781 // calls ZmSearchController's _handleLoadShowResults 782 if (callback) { 783 callback.run(AjxDispatcher.run("GetCalController")); 784 } 785 }; 786 787 ZmCalendarApp.prototype.activate = 788 function(active, viewId) { 789 this._createDeferredFolders(ZmApp.CALENDAR); 790 ZmApp.prototype.activate.apply(this, arguments); 791 792 if (appCtxt.get(ZmSetting.CALENDAR_ENABLED)) { 793 var avm = appCtxt.getAppViewMgr(); 794 var show = (active || appCtxt.get(ZmSetting.CAL_ALWAYS_SHOW_MINI_CAL)) && !avm.isHidden(ZmAppViewMgr.C_TREE_FOOTER, viewId); 795 AjxDispatcher.run("ShowMiniCalendar", show); 796 } 797 }; 798 799 // Online to Offline or Offline to Online; Called from ZmApp.activate and from ZmOffline.enableApps, disableApps 800 ZmCalendarApp.prototype.resetWebClientOfflineOperations = 801 function() { 802 ZmApp.prototype.resetWebClientOfflineOperations.apply(this); 803 var controller = this.getCalController(); 804 if (controller) { 805 controller._resetToolbarOperations(); 806 controller._clearViewActionMenu(); 807 } 808 }; 809 810 /** 811 * Shows the mini-calendar. 812 * 813 * @param {Boolean} show if <code>true</code>, show the mini-calendar 814 * @param {int} delay the delay (in seconds) 815 */ 816 ZmCalendarApp.prototype.showMiniCalendar = 817 function(show, delay) { 818 var mc = AjxDispatcher.run("GetCalController").getMiniCalendar(delay); 819 mc.setSkipNotifyOnPage(show && !this._active); 820 if (!this._active) { 821 mc.setSelectionMode(DwtCalendar.DAY); 822 } 823 appCtxt.getAppViewMgr().displayComponent(ZmAppViewMgr.C_TREE_FOOTER, show); 824 }; 825 826 // common API shared by tasks app 827 /** 828 * Gets the list controller. 829 * 830 * @return {ZmCalViewController} the controller 831 * 832 * @see #getCalController 833 */ 834 ZmCalendarApp.prototype.getListController = 835 function() { 836 return AjxDispatcher.run("GetCalController"); 837 }; 838 839 /** 840 * Gets the calendar controller. 841 * 842 * @return {ZmCalViewController} the controller 843 */ 844 ZmCalendarApp.prototype.getCalController = 845 function(sessionId, searchResultsController) { 846 AjxDispatcher.require(["Startup2", "MailCore", "CalendarCore"]); 847 return this.getSessionController({controllerClass: "ZmCalViewController", 848 sessionId: sessionId || ZmApp.MAIN_SESSION, 849 searchResultsController: searchResultsController}); 850 }; 851 852 /** 853 * Gets the free busy cache. 854 * 855 * @return {ZmFreeBusyCache} free busy cache object 856 */ 857 ZmCalendarApp.prototype.getFreeBusyCache = 858 function() { 859 if (!this._freeBusyCache) { 860 AjxDispatcher.require(["MailCore", "CalendarCore"]); 861 this._freeBusyCache = new ZmFreeBusyCache(this); 862 } 863 return this._freeBusyCache; 864 }; 865 866 /** 867 * Gets the reminder controller. 868 * 869 * @return {ZmReminderController} the controller 870 */ 871 ZmCalendarApp.prototype.getReminderController = 872 function() { 873 if (!this._reminderController) { 874 AjxDispatcher.require(["MailCore", "CalendarCore"]); 875 var calMgr = appCtxt.getCalManager(); 876 this._reminderController = calMgr.getReminderController(); 877 this._reminderController._calController = AjxDispatcher.run("GetCalController"); 878 } 879 return this._reminderController; 880 }; 881 882 /** 883 * Gets the appointment compose controller. 884 * 885 * @return {ZmApptComposeController} the controller 886 */ 887 ZmCalendarApp.prototype.getApptComposeController = 888 function(sessionId) { 889 AjxDispatcher.require(["MailCore", "CalendarCore", "Calendar", "CalendarAppt"]); 890 return this.getSessionController({controllerClass: "ZmApptComposeController", 891 sessionId: sessionId}); 892 }; 893 894 ZmCalendarApp.prototype.getSimpleApptComposeController = 895 function() { 896 AjxDispatcher.require(["MailCore", "CalendarCore", "Calendar", "CalendarAppt"]); 897 return this.getSessionController({controllerClass: "ZmSimpleApptComposeController"}); 898 }; 899 900 ZmCalendarApp.prototype.getApptViewController = 901 function(sessionId) { 902 AjxDispatcher.require(["MailCore", "CalendarCore", "Calendar", "CalendarAppt"]); 903 return this.getSessionController({controllerClass: "ZmApptController", 904 sessionId: sessionId}); 905 }; 906 907 ZmCalendarApp.prototype.initResources = 908 function() { 909 if (!this._locations) { 910 this._locations = new ZmResourceList(ZmCalBaseItem.LOCATION); 911 this._locations.isCanonical = true; 912 } 913 914 if (!this._equipment) { 915 this._equipment = new ZmResourceList(ZmCalBaseItem.EQUIPMENT); 916 this._equipment.isCanonical = true; 917 } 918 }; 919 920 ZmCalendarApp.prototype.loadResources = 921 function() { 922 this.initResources(); 923 924 if (appCtxt.get(ZmSetting.GAL_ENABLED)) { 925 var batchCmd = new ZmBatchCommand(); 926 if (!this._locations.isLoaded) { 927 batchCmd.add(new AjxCallback(this._locations, this._locations.load)); 928 } 929 if (!this._equipment.isLoaded) { 930 batchCmd.add(new AjxCallback(this._equipment, this._equipment.load)); 931 } 932 if (batchCmd._cmds.length) { 933 batchCmd.run(); 934 } 935 } 936 }; 937 938 /** 939 * Gets a list of locations. 940 * 941 * @return {ZmResourceList} the resource list 942 */ 943 ZmCalendarApp.prototype.getLocations = 944 function() { 945 this.initResources(); 946 return this._locations; 947 }; 948 949 /** 950 * Gets a list of equipment. 951 * 952 * @return {ZmResourceList} the resource list 953 */ 954 ZmCalendarApp.prototype.getEquipment = 955 function() { 956 this.initResources(); 957 return this._equipment; 958 }; 959 960 /** 961 * Gets the list of calendar ids for reminders. If calendar packages are not loaded, 962 * gets the list from deferred folder ids. 963 * 964 * @return {Array} an array of ids 965 */ 966 ZmCalendarApp.prototype.getReminderCalendarFolderIds = 967 function() { 968 var folderIds = []; 969 if (AjxDispatcher.loaded("CalendarCore")) { 970 folderIds = AjxDispatcher.run("GetCalController").getReminderCalendarFolderIds(); 971 } else { 972 // will be used in reminder dialog 973 this._folderNames = {}; 974 for (var i = 0; i < this._deferredFolders.length; i++) { 975 var params = this._deferredFolders[i]; 976 folderIds.push(params.obj.id); 977 // _folderNames are used when deferred folders are not created 978 // and calendar name is required. example: calendar name 979 // requirement in reminder module 980 this._folderNames[params.obj.id] = params.obj.name; 981 } 982 } 983 return folderIds; 984 }; 985 986 /** 987 * Gets the list of checked calendar ids. If calendar packages are not loaded, 988 * gets the list from deferred folder ids. 989 * 990 * @param {Boolean} localOnly if <code>true</code>, use local calendar only 991 * @return {Array} an array of ids 992 */ 993 ZmCalendarApp.prototype.getCheckedCalendarFolderIds = 994 function(localOnly, includeTrash) { 995 var folderIds = []; 996 if (AjxDispatcher.loaded("CalendarCore")) { 997 folderIds = AjxDispatcher.run("GetCalController").getCheckedCalendarFolderIds(localOnly, includeTrash); 998 } else { 999 // will be used in reminder dialog 1000 this._folderNames = {}; 1001 for (var i = 0; i < this._deferredFolders.length; i++) { 1002 var params = this._deferredFolders[i]; 1003 var str = (params && params.obj && params.obj.f) ? params.obj.f : ""; 1004 if (str && (str.indexOf(ZmOrganizer.FLAG_CHECKED) != -1)) { 1005 if (localOnly && params.obj.zid != null) { 1006 continue; 1007 } 1008 if (params.obj.id == ZmOrganizer.ID_TRASH && !includeTrash) { 1009 continue; 1010 } 1011 folderIds.push(params.obj.id); 1012 // _folderNames are used when deferred folders are not created 1013 // and calendar name is required. example: calendar name 1014 // requirement in reminder module 1015 this._folderNames[params.obj.id] = params.obj.name; 1016 } 1017 } 1018 } 1019 return folderIds; 1020 }; 1021 1022 /** 1023 * Gets the name of the calendar with specified id. 1024 * 1025 * @param {String} id the id of the calendar 1026 * @return {String} the name 1027 */ 1028 ZmCalendarApp.prototype.getCalendarName = 1029 function(id) { 1030 // _folderNames are used when deferred folders are not created and calendar 1031 // name is required. example: calendar name requirement in reminder module 1032 return appCtxt.getById(id) ? appCtxt.getById(id).name : this._folderNames[id]; 1033 }; 1034 1035 /** 1036 * Creates a new button with a {@link DwtCalendar} as the menu. 1037 * 1038 * @param {DwtComposite} parent the parent 1039 * @param {String} buttonId the button id to fetch inside DOM and append DwtButton to 1040 * @param {AjxListener} dateButtonListener the listener to call when date button is pressed 1041 * @param {AjxListener} dateCalSelectionListener the listener to call when date is selected in {@link DwtCalendar} 1042 */ 1043 ZmCalendarApp.createMiniCalButton = 1044 function(parent, buttonId, dateButtonListener, dateCalSelectionListener, reparent) { 1045 // create button 1046 var params = {parent:parent}; 1047 if (reparent === false) { 1048 params.id = buttonId; 1049 } 1050 var dateButton = new DwtButton(params); 1051 dateButton.addDropDownSelectionListener(dateButtonListener); 1052 //make sure to listen to the tiny left-edge(thats not part of drop-down menu) 1053 dateButton.addSelectionListener(dateButtonListener); 1054 //to keep the image unchanged on hover 1055 dateButton.setDropDownHovImage(null); 1056 dateButton.setData(Dwt.KEY_ID, buttonId); 1057 if (AjxEnv.isIE) { 1058 dateButton.setSize("20"); 1059 } 1060 1061 // create menu for button 1062 var calMenu = new DwtMenu({parent:dateButton, style:DwtMenu.CALENDAR_PICKER_STYLE}); 1063 calMenu.setSize("150"); 1064 calMenu._table.width = "100%"; 1065 dateButton.setMenu(calMenu, true); 1066 1067 // create mini cal for menu for button 1068 var cal = new DwtCalendar({parent:calMenu}); 1069 cal.setData(Dwt.KEY_ID, buttonId); 1070 cal.setSkipNotifyOnPage(true); 1071 var fdow = appCtxt.get(ZmSetting.CAL_FIRST_DAY_OF_WEEK) || 0; 1072 cal.setFirstDayOfWeek(fdow); 1073 cal.addSelectionListener(dateCalSelectionListener); 1074 // add settings change listener on mini cal in case first day of week setting changes 1075 // safety check since this is static code (may not have loaded calendar) 1076 var fdowSetting = appCtxt.getSettings().getSetting(ZmSetting.CAL_FIRST_DAY_OF_WEEK); 1077 if (fdowSetting) { 1078 var listener = new AjxListener(null, ZmCalendarApp._settingChangeListener, cal); 1079 fdowSetting.addChangeListener(listener); 1080 } 1081 1082 if (reparent !== false) { 1083 dateButton.reparentHtmlElement(buttonId); 1084 } 1085 1086 return dateButton; 1087 }; 1088 1089 /** 1090 * Creates a new button with a reminder options as its menu. 1091 * 1092 * @param {DwtComposite} parent the parent 1093 * @param {String} buttonId the button id to fetch inside DOM and append DwtButton to 1094 * @param {AjxListener} buttonListener the listener to call when date button is pressed 1095 * @param {AjxListener} menuSelectionListener the listener to call when date is selected in {@link DwtCalendar} 1096 */ 1097 ZmCalendarApp.createReminderButton = 1098 function(parent, buttonId, buttonListener, menuSelectionListener) { 1099 // create button 1100 var reminderButton = new DwtButton({parent:parent}); 1101 reminderButton.addDropDownSelectionListener(buttonListener); 1102 reminderButton.setData(Dwt.KEY_ID, buttonId); 1103 if (AjxEnv.isIE) { 1104 reminderButton.setSize("20"); 1105 } 1106 1107 // create menu for button 1108 var reminderMenu = new DwtMenu({parent:reminderButton, style:DwtMenu.DROPDOWN_STYLE}); 1109 reminderMenu.setSize("150"); 1110 reminderButton.setMenu(reminderMenu, true); 1111 1112 var defaultWarningTime = appCtxt.get(ZmSetting.CAL_REMINDER_WARNING_TIME); 1113 1114 for (var i = 0; i < ZmCalendarApp.reminderTimeWarningDisplayMsgs.length; i++) { 1115 var optLabel = ZmCalendarApp.__formatLabel(ZmCalendarApp.reminderTimeWarningDisplayMsgs[i], ZmCalendarApp.reminderTimeWarningLabels[i]); 1116 var mi = new DwtMenuItem({parent: reminderMenu, style: DwtMenuItem.NO_STYLE}); 1117 mi.setText(optLabel); 1118 mi.setData("value",ZmCalendarApp.reminderTimeWarningValues[i]); 1119 if(menuSelectionListener) mi.addSelectionListener(menuSelectionListener); 1120 } 1121 1122 // reparent and cleanup 1123 reminderButton.reparentHtmlElement(buttonId); 1124 delete buttonId; 1125 1126 return reminderButton; 1127 }; 1128 1129 /** 1130 * Gets the summary of reminder info from the reminder minutes. 1131 * 1132 * @param {int} reminderMinutes the number of minutes before which reminder should be shown 1133 * @return {String} the summary 1134 */ 1135 ZmCalendarApp.getReminderSummary = 1136 function(reminderMinutes) { 1137 1138 var hoursConvertable = ((reminderMinutes%60) == 0); 1139 var daysConvertable = ((reminderMinutes%(60*24)) == 0); 1140 var weeksConvertable = ((reminderMinutes%(60*24*7)) == 0); 1141 1142 if (reminderMinutes === -1) { return ZmMsg.apptRemindNever; } 1143 if (reminderMinutes === 0) { return ZmMsg.apptRemindAtEventTime; } 1144 if (weeksConvertable) { return ZmCalendarApp.__formatLabel(ZmMsg.apptRemindNWeeksBefore, reminderMinutes/(60*24*7)); } 1145 if (daysConvertable) { return ZmCalendarApp.__formatLabel(ZmMsg.apptRemindNDaysBefore, reminderMinutes/(60*24)); } 1146 if (hoursConvertable) { return ZmCalendarApp.__formatLabel(ZmMsg.apptRemindNHoursBefore, reminderMinutes/60); } 1147 1148 return ZmCalendarApp.__formatLabel(ZmMsg.apptRemindNMinutesBefore, reminderMinutes); 1149 }; 1150 1151 ZmCalendarApp._settingChangeListener = 1152 function(cal, ev) { 1153 if (ev.type != ZmEvent.S_SETTING) { return; } 1154 1155 var setting = ev.source; 1156 if (setting.id == ZmSetting.CAL_FIRST_DAY_OF_WEEK) { 1157 cal.setFirstDayOfWeek(setting.getValue()); 1158 } 1159 }; 1160 1161 ZmCalendarApp.prototype._newCalendarCallback = 1162 function(parent, name, color, url, excludeFb) { 1163 // REVISIT: Do we really want to close the dialog before we 1164 // know if the create succeeds or fails? 1165 var dialog = appCtxt.getNewCalendarDialog(); 1166 dialog.popdown(); 1167 1168 var oc = appCtxt.getOverviewController(); 1169 oc.getTreeController(ZmOrganizer.CALENDAR)._doCreate(parent, name, color, url, excludeFb); 1170 }; 1171 1172 /** 1173 * Adds an invite actions submenu for accept/decline/tentative. 1174 * 1175 * @param {ZmButtonToolBar|ZmActionMenu} parent the parent widget 1176 * @return {ZmActionMenu} the action menu 1177 */ 1178 ZmCalendarApp.addInviteReplyMenu = 1179 function(parent) { 1180 var list = [ZmOperation.EDIT_REPLY_ACCEPT, ZmOperation.EDIT_REPLY_TENTATIVE, ZmOperation.EDIT_REPLY_DECLINE]; 1181 var menu = new ZmActionMenu({parent:parent, menuItems:list}); 1182 parent.setMenu(menu); 1183 return menu; 1184 }; 1185 1186 /** 1187 * Adds an invite actions submenu for accept/decline/tentative. 1188 * 1189 * @param {ZmButtonToolBar|ZmActionMenu} parent the parent widget 1190 * @return {ZmActionMenu} the action menu 1191 */ 1192 ZmCalendarApp.addCalViewMenu = 1193 function(parent) { 1194 var list = [ 1195 ZmOperation.DAY_VIEW, ZmOperation.WORK_WEEK_VIEW, ZmOperation.WEEK_VIEW, 1196 ZmOperation.MONTH_VIEW, ZmOperation.CAL_LIST_VIEW 1197 ]; 1198 if(appCtxt.get(ZmSetting.FREE_BUSY_VIEW_ENABLED)) { 1199 list.push(ZmOperation.FB_VIEW); 1200 } 1201 var menu = new ZmActionMenu({parent:parent, menuItems:list}); 1202 parent.setMenu(menu); 1203 return menu; 1204 }; 1205 1206 ZmCalendarApp.__formatLabel = 1207 function(prefLabel, prefValue) { 1208 prefLabel = prefLabel || ""; 1209 return prefLabel.match(/\{/) ? AjxMessageFormat.format(prefLabel, prefValue) : prefLabel; 1210 }; 1211 1212 /** 1213 * Parses the given string and return reminder info containing units and exact value 1214 * 1215 * @param reminderString reminder string eg. "20 minutes before" 1216 * 1217 * @private 1218 */ 1219 ZmCalendarApp.parseReminderString = 1220 function(reminderString) { 1221 var reminderFormats = {}; 1222 reminderFormats[ZmMsg.apptRemindNDaysBefore] = ZmCalItem.REMINDER_UNIT_DAYS; 1223 reminderFormats[ZmMsg.apptRemindNMinutesBefore] = ZmCalItem.REMINDER_UNIT_MINUTES; 1224 reminderFormats[ZmMsg.apptRemindNHoursBefore] = ZmCalItem.REMINDER_UNIT_HOURS; 1225 reminderFormats[ZmMsg.apptRemindNWeeksBefore] = ZmCalItem.REMINDER_UNIT_WEEKS; 1226 1227 reminderString = AjxStringUtil.trim(reminderString); 1228 var formattedString = reminderString; 1229 var reminderValue = formattedString.replace(/\D/g, ""); 1230 reminderValue = AjxStringUtil.trim(reminderValue); 1231 if (reminderString === ZmMsg.apptRemindAtEventTime) { 1232 return { 1233 reminderValue: 0, 1234 reminderUnits: ZmCalItem.REMINDER_UNIT_MINUTES 1235 } 1236 } 1237 1238 // junk content returns empty reminder (None) 1239 if (reminderValue == "") { 1240 return { 1241 reminderValue: "", 1242 reminderUnits: ZmCalItem.REMINDER_NONE 1243 }; 1244 } 1245 if (reminderValue.indexOf(" ") >= 0) { 1246 reminderValue = reminderValue.split(" ")[0]; 1247 } 1248 1249 // look for standard reminder formats strings 1250 for (var pattern in reminderFormats) { 1251 var formattedContent = ZmCalendarApp.__formatLabel(pattern, reminderValue); 1252 if(formattedContent != "" && formattedContent.toLowerCase() == reminderString.toLowerCase()) { 1253 //Fix for bug: 80651 - set and return object to determine before snooze 1254 return {reminderValue: reminderValue, reminderUnits: reminderFormats[pattern], before: true}; 1255 } 1256 } 1257 1258 var reminderHours = parseInt(reminderValue); 1259 1260 // parse the reminder string for singular units like minute, hour, day etc 1261 var remUnitStrings = {}; 1262 remUnitStrings[ZmCalItem.REMINDER_UNIT_MINUTES] = AjxMsg.minute; 1263 remUnitStrings[ZmCalItem.REMINDER_UNIT_HOURS] = AjxMsg.hour; 1264 remUnitStrings[ZmCalItem.REMINDER_UNIT_DAYS] = AjxMsg.day; 1265 remUnitStrings[ZmCalItem.REMINDER_UNIT_WEEKS] = AjxMsg.week; 1266 1267 //look for matching units 1268 // default unit is hours 1269 var reminderUnits = ZmCalItem.REMINDER_UNIT_HOURS; 1270 1271 for(var i in remUnitStrings) { 1272 if(formattedString.indexOf(remUnitStrings[i]) >= 0) { 1273 reminderUnits = i; 1274 return {reminderValue: reminderHours ? reminderHours : 0, reminderUnits: reminderUnits}; 1275 } 1276 } 1277 1278 // parse the reminder string for plural units like minutes, hours, days etc 1279 var remUnitPluralStrings = {}; 1280 remUnitPluralStrings[ZmCalItem.REMINDER_UNIT_MINUTES] = AjxMsg.minutes; 1281 remUnitPluralStrings[ZmCalItem.REMINDER_UNIT_HOURS] = AjxMsg.hours; 1282 remUnitPluralStrings[ZmCalItem.REMINDER_UNIT_DAYS] = AjxMsg.days; 1283 remUnitPluralStrings[ZmCalItem.REMINDER_UNIT_WEEKS] = AjxMsg.weeks; 1284 1285 for(var i in remUnitPluralStrings) { 1286 if(formattedString.indexOf(remUnitPluralStrings[i]) >= 0) { 1287 reminderUnits = i; 1288 return {reminderValue: reminderHours ? reminderHours : 0, reminderUnits: reminderUnits}; 1289 } 1290 } 1291 // fall back to hours if no matching string found 1292 return {reminderValue: reminderHours ? reminderHours : 0, reminderUnits: reminderUnits}; 1293 }; 1294 1295 ZmCalendarApp.convertReminderUnits = 1296 function(reminderValue, reminderUnits) { 1297 switch (reminderUnits) { 1298 case ZmCalItem.REMINDER_UNIT_MINUTES: return reminderValue; 1299 case ZmCalItem.REMINDER_UNIT_HOURS: return reminderValue*60; 1300 case ZmCalItem.REMINDER_UNIT_DAYS: return reminderValue*60*24; 1301 case ZmCalItem.REMINDER_UNIT_WEEKS: return reminderValue*60*24*7; 1302 default: return 0; 1303 } 1304 }; 1305 1306 ZmCalendarApp.prototype.updateResourceCache = 1307 function(resource) { 1308 var name = resource.getFullName(); 1309 if (name) { 1310 this._resByName[name.toLowerCase()] = resource; 1311 } 1312 var email = resource.getEmail(); 1313 if (email) { 1314 this._resByEmail[email.toLowerCase()] = resource; 1315 } 1316 }; 1317 1318 ZmCalendarApp.prototype._addSettingsChangeListeners = 1319 function() { 1320 1321 ZmApp.prototype._addSettingsChangeListeners.call(this); 1322 1323 if (!this._settingsListener) { 1324 this._settingsListener = new AjxListener(this, this._settingsChangeListener); 1325 } 1326 1327 var settings = appCtxt.getSettings(); 1328 var setting = settings.getSetting(ZmSetting.CAL_ALWAYS_SHOW_MINI_CAL); 1329 if (setting) { 1330 setting.addChangeListener(this._settingListener); 1331 } 1332 setting = settings.getSetting(ZmSetting.CAL_FIRST_DAY_OF_WEEK); 1333 if (setting) { 1334 setting.addChangeListener(this._settingListener); 1335 } 1336 setting = settings.getSetting(ZmSetting.CAL_WORKING_HOURS); 1337 if (setting) { 1338 setting.addChangeListener(this._settingListener); 1339 } 1340 setting = settings.getSetting(ZmSetting.CAL_SHOW_DECLINED_MEETINGS); 1341 if (setting) { 1342 setting.addChangeListener(this._settingListener); 1343 } 1344 1345 var settings = appCtxt.getSettings(); 1346 settings.getSetting(ZmSetting.CAL_SHOW_CALENDAR_WEEK).addChangeListener(this._settingListener); 1347 settings.addChangeListener(this._settingsListener); 1348 }; 1349 1350 /** 1351 * Settings listener to process changed settings. 1352 */ 1353 ZmCalendarApp.prototype._settingChangeListener = 1354 function(ev) { 1355 if (ev.type != ZmEvent.S_SETTING) { return; } 1356 1357 var setting = ev.source; 1358 if (setting.id == ZmSetting.CAL_ALWAYS_SHOW_MINI_CAL) { 1359 if (setting.getValue()) { 1360 var avm = appCtxt.getAppViewMgr(); 1361 var show = !avm.isHidden(ZmAppViewMgr.C_TREE_FOOTER, avm.getCurrentViewId()); 1362 AjxDispatcher.run("ShowMiniCalendar", show); 1363 } else if (!this._active) { 1364 AjxDispatcher.run("ShowMiniCalendar", false); 1365 } 1366 } else if (setting.id == ZmSetting.CAL_FIRST_DAY_OF_WEEK) { 1367 var controller = AjxDispatcher.run("GetCalController"); 1368 var minical = controller.getMiniCalendar(); 1369 1370 var firstDayOfWeek = setting.getValue(); 1371 minical.setFirstDayOfWeek(firstDayOfWeek); 1372 1373 var date = minical.getDate(); 1374 controller.setDate(date, 0, true); 1375 } 1376 else if (setting.id == ZmSetting.CAL_WORKING_HOURS) { 1377 var controller = AjxDispatcher.run("GetCalController"); 1378 var viewMgr = controller.getViewMgr(); 1379 if(viewMgr) { 1380 viewMgr.layoutWorkingHours(); 1381 } 1382 } else if (setting.id == ZmSetting.CAL_SHOW_DECLINED_MEETINGS) { 1383 var controller = AjxDispatcher.run("GetCalController"); 1384 controller.refreshCurrentView(); 1385 } 1386 }; 1387 1388 ZmCalendarApp.prototype._settingsChangeListener = 1389 function(ev) { 1390 if (ev.type != ZmEvent.S_SETTINGS) { return; } 1391 1392 var list = ev.getDetail("settings"); 1393 if (!(list && list.length)) { return; } 1394 1395 for (var i = 0; i < list.length; i++) { 1396 var setting = list[i]; 1397 if (setting.id == ZmSetting.CAL_SHOW_CALENDAR_WEEK) { 1398 var controller = AjxDispatcher.run("GetCalController").recreateMiniCalendar(); 1399 var calMgr = appCtxt.getCalManager(); 1400 calMgr.highlightMiniCal(); 1401 } 1402 } 1403 }; 1404 1405 ZmCalendarApp.prototype.showDayView = 1406 function(date) { 1407 var calController = AjxDispatcher.run("GetCalController"); 1408 var miniCalendar = calController.getMiniCalendar(); 1409 calController.setDate(date, 0, miniCalendar.getForceRollOver()); 1410 if (!calController._viewVisible) { 1411 calController.show(ZmId.VIEW_CAL_DAY); 1412 } 1413 }; 1414 1415 ZmCalendarApp.prototype.getDateToolTip = 1416 function(date, getSimpleToolTip) { 1417 var cc = AjxDispatcher.run("GetCalController"); 1418 return cc.getDayToolTipText(date, null, null, true, getSimpleToolTip); 1419 }; 1420 1421 ZmCalendarApp.prototype.importAppointment = 1422 function(msgId, partId,name) { 1423 var loadCallback = new AjxCallback(this, this._handleImportAppointment, [msgId, partId, name]); 1424 AjxDispatcher.require(["MailCore", "CalendarCore","Calendar"], false, loadCallback); 1425 }; 1426 1427 ZmCalendarApp.prototype._handleImportAppointment = 1428 function(msgId, partId, name) { 1429 if (this._deferredFolders.length != 0) { 1430 this._createDeferredFolders(ZmApp.CALENDAR); 1431 } 1432 var dlg = this._copyToDialog = appCtxt.getChooseFolderDialog(); 1433 var chooseCb = new AjxCallback(this, this._chooserCallback, [msgId, partId, name]); 1434 ZmController.showDialog(dlg, chooseCb, this._getCopyParams(dlg, msgId, partId)); 1435 }; 1436 1437 ZmCalendarApp.prototype._getCopyParams = 1438 function(dlg, msgId, partId) { 1439 return { 1440 data: {msgId:msgId,partId:partId}, 1441 treeIds: [ZmOrganizer.CALENDAR], 1442 overviewId: dlg.getOverviewId(this._name), 1443 title: ZmMsg.addToCalendar, 1444 description: ZmMsg.targetFolder, 1445 appName: ZmApp.CALENDAR 1446 }; 1447 }; 1448 1449 ZmCalendarApp.prototype._chooserCallback = 1450 function(msgId, partId, name, folder) { 1451 1452 1453 var jsonObj = {ImportAppointmentsRequest:{_jsns:"urn:zimbraMail"}}; 1454 var request = jsonObj.ImportAppointmentsRequest; 1455 request.l = folder.id; 1456 request.ct = "text/calendar"; 1457 1458 var m = request.content = {}; 1459 m.mid = msgId; 1460 m.part = partId; 1461 1462 var params = { 1463 jsonObj: jsonObj, 1464 asyncMode: true, 1465 callback: (new AjxCallback(this, this._handleImportApptResponse, [folder.id])), 1466 errorCallback: (new AjxCallback(this, this._handleImportApptError)) 1467 }; 1468 appCtxt.getAppController().sendRequest(params); 1469 1470 }; 1471 1472 ZmCalendarApp.prototype._handleImportApptResponse = 1473 function(folderId,response) { 1474 appCtxt.getAppController().setStatusMsg(ZmMsg.addedToCalendar); 1475 appCtxt.getChooseFolderDialog().popdown(); 1476 1477 var ac = window.parentAppCtxt || window.appCtxt; 1478 if(ac.get(ZmSetting.CAL_ALWAYS_SHOW_MINI_CAL)) { 1479 var calMgr = ac.getCalManager(); 1480 calMgr.getMiniCalCache().clearCache(); 1481 calMgr.highlightMiniCal(); 1482 } 1483 }; 1484 1485 ZmCalendarApp.prototype._handleImportApptError = 1486 function(ex) { 1487 appCtxt.getAppController().setStatusMsg(ZmMsg.errorImportAppt, ZmStatusView.LEVEL_CRITICAL); 1488 }; 1489 1490 /** 1491 * Returns the reminder warning time display options formatted for preferences 1492 * we create preferences reminder button here . 1493 */ 1494 ZmCalendarApp.getReminderTimeWarningDisplayOptions = 1495 function() { 1496 var returnArr = []; 1497 for (var i = 0; i < ZmCalendarApp.reminderTimeWarningDisplayMsgs.length; i++) { 1498 returnArr.push(ZmCalendarApp.__formatLabel(ZmCalendarApp.reminderTimeWarningDisplayMsgs[i], ZmCalendarApp.reminderTimeWarningLabels[i])); 1499 1500 } 1501 return returnArr; 1502 }; 1503 1504 /** 1505 * On doing save, we modify the request and map zimbraPrefCalendarApptReminderWarningTimevalue 1506 * so that the value of never, 0, is not changed at server. 1507 * If never is selected in reminder dropdown, we map never value -1 to previous value, 0 1508 * and if 'at time of event' is chosen, we map 0 to -1 while constructing request. 1509 **/ 1510 1511 ZmCalendarApp.setDefaultReminderTimePrefValueOnSave = 1512 function(pref, value, list) { 1513 value === 0 ? (value = -1) : (value === -1 ? value =0 : ''); 1514 pref.setValue(value); 1515 list.push(pref); 1516 }; 1517 1518 /** 1519 * Client side mapping of never is -1 and 'at time of event' is 0. 1520 * If never is chosen in default reminder dropdown, user saves his preferences. We then modify the request 1521 * and set the pref zimbraPrefCalendarApptReminderWarningTimevalue value to 0, to make the behaviour 1522 * backward compatible, as earlier never was mapped to 0. Now, after reload, the value of pref zimbraPrefCalendarApptReminderWarningTimevalue 1523 * in client side i.e ZmSetting.CAL_REMINDER_WARNING_TIME, is 0 as the server returns me this value. 1524 * This was causing issue in the view of reminder option in pref section and while composing a new appt. 1525 * So, here we map default reminder pref to its client side mapping. 1526 * Same thing with 'at time of event'. 1527 */ 1528 1529 ZmCalendarApp.postLoadSetDefaultReminderValue = function() { 1530 /** 1531 * This function is called when after reload, when you click on calendar tab or click on calendar icon 1532 * in preferences. And, after reload, we want to set the value of default reminder pref only one time when 1533 * the calendar tab is clicked or calendar pref is clicked. So, we have used global variable postLoadSetReminderCalled 1534 * as a check for that. Other option for doing that would be to call this function from ZmApp.prototype._postLoad 1535 * and then no need for doing check based on variable postLoadSetReminderCalled, but that be 1536 * something calling during the initial page's load, so I avoided that . 1537 */ 1538 1539 if (ZmCalendarApp.postLoadSetReminderCalled) { 1540 return; 1541 } 1542 var defaultWarningTime = appCtxt.get(ZmSetting.CAL_REMINDER_WARNING_TIME); 1543 if (defaultWarningTime === -1 || defaultWarningTime === 0) { // never or 'at time of event' was chosen in defaultreminderpref dropdown before load 1544 defaultWarningTime === -1 ? (defaultWarningTime = 0) : (defaultWarningTime = -1); 1545 appCtxt.set(ZmSetting.CAL_REMINDER_WARNING_TIME,defaultWarningTime); 1546 } 1547 ZmCalendarApp.postLoadSetReminderCalled = true; 1548 }; 1549