sogo/UI/WebServerResources/js/Scheduler.services.js.map
2015-08-12 09:43:55 -04:00

1 line
58 KiB
Plaintext

{"version":3,"file":"Scheduler.services.js","sources":["Scheduler/Calendar.service.js","Scheduler/Component.service.js"],"names":["Calendar","futureCalendarData","this","init","name","id","newCalendarData","$$resource","create","angular","extend","$acl","$$Acl","$factory","$q","$timeout","$log","Settings","Resource","Component","Acl","activeUser","$Component","module","e","factory","$add","calendar","list","sibling","i","isWebCalendar","$webcalendars","isSubscription","$subscriptions","$calendars","_","find","o","localeCompare","indexOf","pluck","splice","$findAll","data","_this","forEach","push","$get","$subscribe","uid","path","userResource","fetch","then","calendarData","$addWebCalendar","url","d","defer","urls","webCalendarURL","reject","post","isEditable","isRemote","owner","login","debug","JSON","stringify","undefined","resolve","promise","prototype","isOwned","isSuperUser","getClassName","base","isUndefined","$rename","$save","$delete","remove","status","save","$omit","$setActivation","active","$getComponent","componentId","recurrenceId","$find","value","key","futureComponentData","pid","newComponentData","newguid","$unwrap","isNew","Preferences","Gravatar","$Preferences","$gravatar","baseURL","timeFormat","$query","search","$queryEvents","sort","asc","filterpopup","$queryTasks","ready","settings","EventsFilterState","TasksFilterState","EventsSortingState","parseInt","TasksSortingState","show_completed","ShowCompletedTasks","$categories","defaults","SOGoCalendarCategoriesColors","SOGoTimeFormat","$filter","type","options","now","Date","day","getDate","month","getMonth","year","getFullYear","queryKey","capitalize","params","otherType","dirty","each","keys","isDefined","$unwrapCollection","calendarId","occurrenceId","join","filterCategories","query","re","RegExp","filter","category","saveSelectedList","componentType","$eventsBlocksForView","view","date","viewAction","startDate","endDate","beginOfWeek","setTime","getTime","addDays","setDate","setMonth","endOfWeek","$eventsBlocks","deferred","toLowerCase","sd","getDayString","ed","components","blocks","reduce","events","objects","eventData","componentData","object","eventsFields","start","c_startdate","hour","getHourString","flatten","block","component","nbr","length","$blocks","fields","invoke","categories","repeat","alarm","action","quantity","unit","reference","relation","classification","substring","end","dueDate","due","$isRecurrent","days","byDayMask","occurrence","frequency","byday","toString","interval","monthdays","months","count","until","asDate","$hasCustomRepeat","hasCustomRepeat","units","M","H","D","W","match","exec","SOGoCalendarDefaultReminder","$hasAlarm","destinationCalendar","organizer","email","$image","freebusy","updateFreeBusyCoverage","attendees","attendee","image","updateFreeBusy","b","isReadOnly","isEditableOccurrence","isInvitation","userHasRSVP","isInvitationOccurrence","enablePercentComplete","coversFreeBusy","quarter","roundedStart","roundedEnd","startQuarter","getMinutes","endQuarter","setMinutes","daysUpTo","index","hourKey","currentDay","dayKey","getHours","beginOfDay","addMinutes","sday","eday","map","c_folder","addAttendee","card","c_cn","$preferredEmail","role","c_uid","hasAttendee","emails","canRemindAttendeesByEmail","addAttachUrl","attachUrl","attachUrls","deleteAttachUrl","$reset","$shadowData","$reply","reply","delegatedTo","$futureComponentData","isError","error","formatTime","dateString","hours","minutes","copy","startTime","endTime","stringWithSeparator"],"mappings":"CAEA,WACE,YAOA,SAASA,UAASC,oBAGhB,GADAC,KAAKC,KAAKF,oBACNC,KAAKE,OAASF,KAAKG,GAAI,CAEzB,GAAIC,iBAAkBN,SAASO,WAAWC,OAAO,eAAgBN,KAAKE,KACtEK,SAAQC,OAAOR,KAAMI,iBAEnBJ,KAAKG,KACPH,KAAKS,KAAO,GAAIX,UAASY,MAAM,YAAcV,KAAKG,KAStDL,SAASa,UAAY,KAAM,WAAY,OAAQ,aAAc,WAAY,YAAa,MAAO,SAASC,GAAIC,SAAUC,KAAMC,SAAUC,SAAUC,UAAWC,KAWvJ,MAVAX,SAAQC,OAAOV,UACbc,GAAIA,GACJC,SAAUA,SACVC,KAAMA,KACNT,WAAY,GAAIW,UAASD,SAASI,WAAW,aAAe,WAAYJ,SAASI,cACjFC,WAAYH,UACZP,MAAOQ,IACPC,WAAYJ,SAASI,eAGhBrB,UAOT,KACES,QAAQc,OAAO,oBAEjB,MAAMC,GACJf,QAAQc,OAAO,oBAAqB,gBAEtCd,QAAQc,OAAO,oBACZE,QAAQ,WAAYzB,SAASa,UAOhCb,SAAS0B,KAAO,SAASC,UAEvB,GAAIC,MAAMC,QAASC,CAGjBF,MADED,SAASI,cACJ7B,KAAK8B,cACLL,SAASM,eACT/B,KAAKgC,eAELhC,KAAKiC,WAEdN,QAAUO,EAAEC,KAAKT,KAAM,SAASU,GAC9B,MAAgB,YAARA,EAAEjC,IACsC,IAAxCiC,EAAElC,KAAKmC,cAAcZ,SAASvB,QAExC0B,EAAID,QAAUO,EAAEI,QAAQJ,EAAEK,MAAMb,KAAM,MAAOC,QAAQxB,IAAM,EAC3DuB,KAAKc,OAAOZ,EAAG,EAAGH,WASpB3B,SAAS2C,SAAW,SAASC,MAC3B,GAAIC,OAAQ3C,IAgBZ,OAfI0C,QACF1C,KAAKiC,cACLjC,KAAKgC,kBACLhC,KAAK8B,iBAELvB,QAAQqC,QAAQF,KAAM,SAASN,EAAGR,GAChC,GAAIH,UAAW,GAAI3B,UAASsC,EACxBX,UAASI,cACXc,MAAMb,cAAce,KAAKpB,UAClBA,SAASM,eAChBY,MAAMX,eAAea,KAAKpB,UAE1BkB,MAAMV,WAAWY,KAAKpB,aAGrBzB,KAAKiC,YASdnC,SAASgD,KAAO,SAAS3C,IACvB,GAAIsB,SAQJ,OANAA,UAAWS,EAAEC,KAAKrC,SAASmC,WAAY,SAASG,GAAK,MAAOA,GAAEjC,IAAMA,KAC/DsB,WACHA,SAAWS,EAAEC,KAAKrC,SAASkC,eAAgB,SAASI,GAAK,MAAOA,GAAEjC,IAAMA,MACrEsB,WACHA,SAAWS,EAAEC,KAAKrC,SAASgC,cAAe,SAASM,GAAK,MAAOA,GAAEjC,IAAMA,MAElEsB,UAUT3B,SAASiD,WAAa,SAASC,IAAKC,MAClC,GAAIN,OAAQ3C,IACZ,OAAOF,UAASO,WAAW6C,aAAaF,KAAKG,MAAMF,KAAM,aAAaG,KAAK,SAASC,cAClF,GAAI5B,UAAW,GAAI3B,UAASuD,aAM5B,OALKnB,GAAEC,KAAKQ,MAAMX,eAAgB,SAASI,GACzC,MAAOA,GAAEjC,IAAMkD,aAAalD,MAE5BL,SAAS0B,KAAKC,UAETA,YAUX3B,SAASwD,gBAAkB,SAASC,KAClC,GAAIZ,OAAQ3C,KACRwD,EAAI1D,SAASc,GAAG6C,OA6BpB,OA3BIvB,GAAEC,KAAKQ,MAAMb,cAAe,SAASM,GACrC,MAAOA,GAAEsB,KAAKC,gBAAkBJ,MAGlCC,EAAEI,SAGF9D,SAASO,WAAWwD,KAAK,KAAM,kBAAoBN,IAAKA,MAAOH,KAAK,SAASC,cAC3E9C,QAAQC,OAAO6C,cACbxB,eAAe,EACfiC,YAAY,EACZC,UAAU,EACVC,MAAOlE,SAASqB,WAAW8C,MAC3BP,MAAQC,eAAgBJ,MAE1B,IAAI9B,UAAW,GAAI3B,UAASuD,aAC5BvD,UAAS0B,KAAKC,UACd3B,SAASO,WAAW8C,MAAM1B,SAAStB,GAAI,UAAUiD,KAAK,SAASV,MAE7D5C,SAASgB,KAAKoD,MAAMC,KAAKC,UAAU1B,KAAM2B,OAAW,MAEtDb,EAAEc,WACD,WACDd,EAAEI,WAICJ,EAAEe,SASXzE,SAAS0E,UAAUvE,KAAO,SAASyC,MACjCnC,QAAQC,OAAOR,KAAM0C,MAErB1C,KAAKyE,QAAU3E,SAASqB,WAAWuD,aAAe1E,KAAKgE,OAASlE,SAASqB,WAAW8C,MACpFjE,KAAK+B,gBAAkB/B,KAAK+D,UAAY/D,KAAKgE,OAASlE,SAASqB,WAAW8C,OAS5EnE,SAAS0E,UAAUG,aAAe,SAASC,MAGzC,MAFIrE,SAAQsE,YAAYD,QACtBA,KAAO,MACFA,KAAO,UAAY5E,KAAKG,IAUjCL,SAAS0E,UAAUM,QAAU,SAAS5E,MACpC,GAAI0B,GAAIM,EAAEI,QAAQJ,EAAEK,MAAMzC,SAASmC,WAAY,MAAOjC,KAAKG,GAI3D,OAHAH,MAAKE,KAAOA,KACZJ,SAASmC,WAAWO,OAAOZ,EAAG,GAC9B9B,SAAS0B,KAAKxB,MACPA,KAAK+E,SASdjF,SAAS0E,UAAUQ,QAAU,WAC3B,GAEItD,MACA6C,QAHA5B,MAAQ3C,KACRwD,EAAI1D,SAASc,GAAG6C,OAuBpB,OAnBIzD,MAAK+B,gBACPwC,QAAUzE,SAASO,WAAW8C,MAAMnD,KAAKG,GAAI,eAC7CuB,KAAO5B,SAASkC,iBAGhBuC,QAAUzE,SAASO,WAAW4E,OAAOjF,KAAKG,IAExCuB,KADE1B,KAAK6B,cACA/B,SAASgC,cAEThC,SAASmC,YAGpBsC,QAAQnB,KAAK,WACX,GAAIxB,GAAIM,EAAEI,QAAQJ,EAAEK,MAAMb,KAAM,MAAOiB,MAAMxC,GAC7CuB,MAAKc,OAAOZ,EAAG,GACf4B,EAAEc,WACD,SAAS5B,KAAMwC,QAChB1B,EAAEI,OAAOlB,QAEJc,EAAEe,SASXzE,SAAS0E,UAAUO,MAAQ,WACzB,MAAOjF,UAASO,WAAW8E,KAAKnF,KAAKG,GAAIH,KAAKoF,SAAShC,KAAK,SAASV,MACnE,MAAOA,SAUX5C,SAAS0E,UAAUa,eAAiB,WAClC,MAAOvF,UAASO,WAAW8C,MAAMnD,KAAKG,IAAKH,KAAKsF,OAAO,GAAG,MAAQ,mBASpExF,SAAS0E,UAAUe,cAAgB,SAASC,YAAaC,cACvD,MAAO3F,UAASsB,WAAWsE,MAAM1F,KAAKG,GAAIqF,YAAaC,eASzD3F,SAAS0E,UAAUY,MAAQ,WACzB,GAAI3D,YAOJ,OANAlB,SAAQqC,QAAQ5C,KAAM,SAAS2F,MAAOC,KACzB,eAAPA,KACU,KAAVA,IAAI,KACNnE,SAASmE,KAAOD,SAGblE,aC7SX,WACE,YAOA,SAASR,WAAU4E,qBAEjB,GAAwC,kBAA7BA,qBAAoBzC,MAE7B,GADApD,KAAKC,KAAK4F,qBACN7F,KAAK8F,MAAQ9F,KAAKG,GAAI,CAGxB,GAAI4F,kBAAmB9E,UAAUZ,WAAW2F,QAAQhG,KAAK8F,IACzD9F,MAAKiG,QAAQF,kBACb/F,KAAKkG,OAAQ,OAKflG,MAAKiG,QAAQJ,qBASjB5E,UAAUN,UAAY,KAAM,WAAY,OAAQ,aAAc,cAAe,WAAY,WAAY,SAASC,GAAIC,SAAUC,KAAMC,SAAUoF,YAAaC,SAAUpF,UAuCjK,MAtCAT,SAAQC,OAAOS,WACbL,GAAIA,GACJC,SAAUA,SACVC,KAAMA,KACNuF,aAAcF,YACdG,UAAWF,SACX/F,WAAY,GAAIW,UAASD,SAASwF,UAAWxF,SAASI,cACtDqF,WAAY,QAEZC,QAAUd,MAAO,GAAIe,OAAQ,2BAE7BC,cAAgBC,KAAM,QAASC,IAAK,EAAGC,YAAa,cAEpDC,aAAeH,KAAM,SAAUC,IAAK,EAAGC,YAAa,qBAEtDX,YAAYa,QAAQ5D,KAAK,WAEnB+C,YAAYc,SAASnH,SAASoH,oBAChCjG,UAAU0F,aAAaG,YAAcX,YAAYc,SAASnH,SAASoH,mBACjEf,YAAYc,SAASnH,SAASqH,mBAChClG,UAAU8F,YAAYD,YAAcX,YAAYc,SAASnH,SAASqH,kBAChEhB,YAAYc,SAASnH,SAASsH,qBAChCnG,UAAU0F,aAAaC,KAAOT,YAAYc,SAASnH,SAASsH,mBAAmB,GAC/EnG,UAAU0F,aAAaE,IAAMQ,SAASlB,YAAYc,SAASnH,SAASsH,mBAAmB,KAErFjB,YAAYc,SAASnH,SAASwH,oBAChCrG,UAAU8F,YAAYH,KAAOT,YAAYc,SAASnH,SAASwH,kBAAkB,GAC7ErG,UAAU8F,YAAYF,IAAMQ,SAASlB,YAAYc,SAASnH,SAASwH,kBAAkB,KAEvFrG,UAAU8F,YAAYQ,eAAiBF,SAASlB,YAAYc,SAASO,oBAErEvG,UAAUwG,YAActB,YAAYuB,SAASC,6BAEzCxB,YAAYuB,SAASE,iBACvB3G,UAAUuF,WAAaL,YAAYuB,SAASE,kBAIzC3G,WAOT,KACEV,QAAQc,OAAO,oBAEjB,MAAMC,GACJf,QAAQc,OAAO,oBAAqB,gBAEtCd,QAAQc,OAAO,oBACZE,QAAQ,YAAaN,UAAUN,UAUlCM,UAAU4G,QAAU,SAASC,KAAMC,SACjC,GAAIpF,OAAQ3C,KACRgI,IAAM,GAAIC,MACVC,IAAMF,IAAIG,UACVC,MAAQJ,IAAIK,WAAa,EACzBC,KAAON,IAAIO,cACXC,SAAW,SAAWV,KAAKW,aAC3BC,QACER,IAAK,GAAKI,MAAgB,GAARF,MAAW,IAAI,IAAMA,OAAe,GAANF,IAAS,IAAI,IAAMA,IAGzE,OAAOlI,MAAKqG,aAAaW,QAAQ5D,KAAK,WACpC,GAAIyC,qBAEA8C,UADAC,OAAQ,CA8BZ,OA3BArI,SAAQC,OAAOmC,MAAM8D,OAAQiC,QAEzBX,SACF7F,EAAE2G,KAAK3G,EAAE4G,KAAKf,SAAU,SAASnC,KAE/BgD,OAAUjG,MAAM8D,OAAOb,MAAQmC,QAAQnC,MAAQ3E,UAAUwF,OAAOb,KACrD,UAAPA,KAAmBmC,QAAQnC,KAC7BgD,OAAQ,EAEDrI,QAAQwI,UAAUpG,MAAM8D,OAAOb,MACtCjD,MAAM8D,OAAOb,KAAOmC,QAAQnC,KAE5BjD,MAAM6F,UAAU5C,KAAOmC,QAAQnC,OAKrCC,oBAAsBlD,MAAMtC,WAAW8C,MAAM,KAAM2E,KAAO,OACbvH,QAAQC,OAAOmC,MAAM6F,UAAW7F,MAAM8D,SAGnFkC,UAAqB,SAARb,KAAkB,UAAY,SACvCc,cACK3H,WAAU0H,WACjB1H,UAAUH,KAAKoD,MAAM,mBAAqByE,YAGrChG,MAAMqG,kBAAkBlB,KAAMjC,wBAYzC5E,UAAUyE,MAAQ,SAASuD,WAAYzD,YAAa0D,cAClD,GAAIrD,qBAAqB5C,MAAQgG,WAAYzD,YAO7C,OALI0D,eACFjG,KAAKJ,KAAKqG,cAEZrD,oBAAsB7F,KAAKK,WAAW8C,MAAMF,KAAKkG,KAAK,KAAM,QAErD,GAAIlI,WAAU4E,sBASvB5E,UAAUmI,iBAAmB,SAASC,OACpC,GAAIC,IAAK,GAAIC,QAAOF,MAAO,IAC3B,OAAOnH,GAAEsH,OAAOtH,EAAE4G,KAAK7H,UAAUwG,aAAc,SAASgC,UACtD,MAA8B,IAAvBA,SAAS/C,OAAO4C,OAU3BrI,UAAUyI,iBAAmB,SAASC,eACpC,MAAO3J,MAAKK,WAAWwD,KAAK,KAAM,oBAAsBnC,KAAMiI,cAAgB,cAUhF1I,UAAU2I,qBAAuB,SAASC,KAAMC,MAC9C,GAAIC,YAAYC,UAAWC,OAwB3B,OAtBY,OAARJ,MACFE,WAAa,UACbC,UAAYC,QAAUH,MAEP,QAARD,MACPE,WAAa,WACbC,UAAYF,KAAKI,cACjBD,QAAU,GAAIhC,MACdgC,QAAQE,QAAQH,UAAUI,WAC1BH,QAAQI,QAAQ,IAED,SAARR,OACPE,WAAa,YACbC,UAAYF,KACZE,UAAUM,QAAQ,GAClBN,UAAYA,UAAUE,cACtBD,QAAU,GAAIhC,MACdgC,QAAQE,QAAQH,UAAUI,WAC1BH,QAAQM,SAASN,QAAQ5B,WAAa,GACtC4B,QAAQI,QAAQ,IAChBJ,QAAUA,QAAQO,aAEbxK,KAAKyK,cAAcV,WAAYC,UAAWC,UAWnDhJ,UAAUwJ,cAAgB,SAASZ,KAAMG,UAAWC,SAClD,GAAIvB,QAAQ7C,oBAAqBjE,EAC7B8I,SAAWzJ,UAAUL,GAAG6C,OAsC5B,OApCAiF,SAAWmB,KAAMA,KAAKc,cAAeC,GAAIZ,UAAUa,eAAgBC,GAAIb,QAAQY,gBAC/E5J,UAAUH,KAAKoD,MAAM,gBAAkBC,KAAKC,UAAUsE,OAAQrE,OAAW,IACzEwB,oBAAsB7F,KAAKK,WAAW8C,MAAM,KAAM,eAAgBuF,QAClE7C,oBAAoBzC,KAAK,SAASV,MAChCzB,UAAUJ,SAAS,WACjB,GAAIkK,eAAiBC,SAiBrB,KAdA9I,EAAE+I,OAAOvI,KAAKwI,OAAQ,SAASC,QAASC,UAAWxJ,GACjD,GAAIyJ,eAAgBnJ,EAAEoJ,OAAO5I,KAAK6I,aAAcH,WAC5CI,MAAQ,GAAIvD,MAAiC,IAA5BoD,cAAcI,YAGnC,OAFAJ,eAAcK,KAAOF,MAAMG,gBAC3BR,QAAQtI,KAAK,GAAI5B,WAAUoK,gBACpBF,SACNJ,YAGH7I,EAAE2G,KAAK3G,EAAE0J,QAAQlJ,KAAKsI,QAAS,SAASa,OACtCA,MAAMC,UAAYf,WAAWc,MAAME,OAIhCnK,EAAI,EAAGA,EAAIc,KAAKsI,OAAOgB,OAAQpK,IAClCoJ,OAAOhB,UAAUa,gBAAkBnI,KAAKsI,OAAOpJ,GAC/CoI,UAAUK,QAAQ,EAGpBpJ,WAAUH,KAAKoD,MAAM,iBAAmBhC,EAAE4G,KAAKkC,QAAQgB,OAAS,KAGhE/K,UAAUgL,QAAUjB,OAEpBN,SAASpG,QAAQ0G,WAElBN,SAAS9G,QAEL8G,SAASnG,SAUlBtD,UAAU+H,kBAAoB,SAASlB,KAAMjC,qBAC3C,GACIkF,cAEJ,OAAOlF,qBAAoBzC,KAAK,SAASV,MACvC,MAAOzB,WAAUJ,SAAS,WACxB,GAAIqL,QAAShK,EAAEiK,OAAOzJ,KAAKwJ,OAAQ,cAcnC,OAXAhK,GAAE+I,OAAOvI,KAAKoF,MAAO,SAASiD,WAAYM,cAAezJ,GACvD,GAAIc,MAAOR,EAAEoJ,OAAOY,OAAQb,cAE5B,OADAN,YAAWlI,KAAK,GAAI5B,WAAUyB,OACvBqI,YACNA,YAEH9J,UAAUH,KAAKoD,MAAM,WAAa4D,KAAO,WAAaiD,WAAWiB,OAAS,KAG1E/K,UAAU,IAAM6G,MAAQiD,WAEjBA,gBAWb9J,UAAUuD,UAAUvE,KAAO,SAASyC,MAClC,GAAIC,OAAQ3C,IAyBZ,IAvBAA,KAAKoM,cACLpM,KAAKqM,UACLrM,KAAKsM,OAAUC,OAAQ,UAAWC,SAAU,EAAGC,KAAM,UAAWC,UAAW,SAAUC,SAAU,SAC/F3M,KAAKkF,OAAS,gBACd3E,QAAQC,OAAOR,KAAM0C,MAErBzB,UAAUoF,aAAaW,QAAQ5D,KAAK,WAClC,GAAI0E,MAAsB,eAAdnF,MAAMmF,KAAwB,SAAW,OAGrDnF,OAAMiK,eAAiBjK,MAAMiK,gBAC3B3L,UAAUoF,aAAaqB,SAAS,eAAiBI,KAAO,yBAAyB6C,gBAGjF3K,KAAKgK,YACPhK,KAAKwL,MAAQ,GAAIvD,MAAKjI,KAAKgK,UAAU6C,UAAU,EAAE,IAAM,IAAM7M,KAAKgK,UAAU6C,UAAU,GAAG,MACvF7M,KAAKiK,UACPjK,KAAK8M,IAAM,GAAI7E,MAAKjI,KAAKiK,QAAQ4C,UAAU,EAAE,IAAM,IAAM7M,KAAKiK,QAAQ4C,UAAU,GAAG,MACjF7M,KAAK+M,UACP/M,KAAKgN,IAAM,GAAI/E,MAAKjI,KAAK+M,QAAQF,UAAU,EAAE,IAAM,IAAM7M,KAAK+M,QAAQF,UAAU,GAAG,MAGrF7M,KAAKiN,aAAe1M,QAAQwI,UAAUrG,KAAK2J,QACvCrM,KAAKqM,OAAOa,KAAM,CACpB,GAAIC,WAAYjL,EAAEC,KAAKnC,KAAKqM,OAAOa,KAAM,SAAS9K,GAChD,MAAO7B,SAAQwI,UAAU3G,EAAEgL,aAEzBD,YAC2B,UAAzBnN,KAAKqM,OAAOgB,YACdrN,KAAKqM,OAAO/D,MAASgF,OAAO,IAC9BtN,KAAKqM,OAAOjE,OACVN,KAAM,QACNsF,WAAYD,UAAUC,WAAWG,WACjCrF,IAAKiF,UAAUjF,SAInBlI,MAAKqM,OAAOa,OAEV3M,SAAQsE,YAAY7E,KAAKqM,OAAOgB,aAClCrN,KAAKqM,OAAOgB,UAAY,SACtB9M,QAAQsE,YAAY7E,KAAKqM,OAAOmB,YAClCxN,KAAKqM,OAAOmB,SAAW,GACrBjN,QAAQsE,YAAY7E,KAAKqM,OAAOjE,SAClCpI,KAAKqM,OAAOjE,OAAUgF,WAAY,IAAKlF,IAAK,KAAMJ,KAAM,eACtDvH,QAAQsE,YAAY7E,KAAKqM,OAAOoB,aAClCzN,KAAKqM,OAAOoB,cACVlN,QAAQsE,YAAY7E,KAAKqM,OAAOqB,UAClC1N,KAAKqM,OAAOqB,WACVnN,QAAQsE,YAAY7E,KAAKqM,OAAO/D,QAClCtI,KAAKqM,OAAO/D,SACVtI,KAAKqM,OAAOsB,MACd3N,KAAKqM,OAAOS,IAAM,QACX9M,KAAKqM,OAAOuB,OACnB5N,KAAKqM,OAAOS,IAAM,QAClB9M,KAAKqM,OAAOuB,MAAQ5N,KAAKqM,OAAOuB,MAAMf,UAAU,EAAE,IAAIgB,UAGtD7N,KAAKqM,OAAOS,IAAM,QACpB9M,KAAK8N,iBAAmB9N,KAAK+N,kBAEzB/N,KAAKkG,MAEPjF,UAAUoF,aAAaW,QAAQ5D,KAAK,WAClC,GAAI4K,QAAUC,EAAG,UAAWC,EAAG,QAASC,EAAG,OAAQC,EAAG,SAClDC,MAAQ,uBAAuBC,KAAKrN,UAAUoF,aAAaqB,SAAS6G,4BACpEF,SACF1L,MAAM6L,WAAY,EAClB7L,MAAM2J,MAAME,SAAWnF,SAASgH,MAAM,IACtC1L,MAAM2J,MAAMG,KAAOuB,MAAMK,MAAM,OAKnCrO,KAAKwO,UAAYjO,QAAQwI,UAAUrG,KAAK4J,OAI1CtM,KAAKyO,oBAAsBzO,KAAK8F,IAE5B9F,KAAK0O,WAAa1O,KAAK0O,UAAUC,QACnC3O,KAAK0O,UAAUE,OAAS3N,UAAUqF,UAAUtG,KAAK0O,UAAUC,MAAO,KAIpE3O,KAAK6O,SAAW7O,KAAK8O,yBAEjB9O,KAAK+O,WACP7M,EAAE2G,KAAK7I,KAAK+O,UAAW,SAASC,UAC9BA,SAASC,MAAQhO,UAAUqF,UAAU0I,SAASL,MAAO,IACrDhM,MAAMuM,eAAeF,aAW3B/N,UAAUuD,UAAUuJ,gBAAkB,WACpC,GAAIoB,GAAI5O,QAAQwI,UAAU/I,KAAKqM,UAC1BrM,KAAKqM,OAAOmB,SAAW,GACvBxN,KAAKqM,OAAOa,MAAQlN,KAAKqM,OAAOa,KAAKlB,OAAS,GAC9ChM,KAAKqM,OAAOoB,WAAazN,KAAKqM,OAAOoB,UAAUzB,OAAS,GACxDhM,KAAKqM,OAAOqB,QAAU1N,KAAKqM,OAAOqB,OAAO1B,OAAS,EACvD,OAAOmD,IASTlO,UAAUuD,UAAUV,WAAa,WAC/B,OAAS9D,KAAKkJ,eAAiBlJ,KAAKoP,YAStCnO,UAAUuD,UAAU6K,qBAAuB,WACzC,MAAQrP,MAAKkJ,eAAiBlJ,KAAKoP,YASrCnO,UAAUuD,UAAU8K,aAAe,WACjC,OAAStP,KAAKkJ,cAAgBlJ,KAAKuP,aASrCtO,UAAUuD,UAAUgL,uBAAyB,WAC3C,MAAQxP,MAAKkJ,cAAgBlJ,KAAKuP,aASpCtO,UAAUuD,UAAU4K,WAAa,WAC/B,MAAQpP,MAAKoP,aAAepP,KAAKuP,aAUnCtO,UAAUuD,UAAUiL,sBAAwB,WAC1C,MAAQzP,MAAK8L,UACU,iBAAf9L,KAAKkF,QACU,aAAflF,KAAKkF,QASfjE,UAAUuD,UAAUkL,eAAiB,SAASxH,IAAKwD,KAAMiE,SACvD,GAAIR,GAAK5O,QAAQwI,UAAU/I,KAAK6O,SAAS3G,OAChC3H,QAAQwI,UAAU/I,KAAK6O,SAAS3G,KAAKwD,QACA,GAArC1L,KAAK6O,SAAS3G,KAAKwD,MAAMiE,QAClC,OAAOR,IASTlO,UAAUuD,UAAUsK,uBAAyB,WAC3C,GAAInM,OAAQ3C,KAAM6O,WAElB,IAAI7O,KAAKwL,OAASxL,KAAK8M,IAAK,CAC1B,GAAI8C,cAAe,GAAI3H,MAAKjI,KAAKwL,MAAMpB,WACnCyF,WAAa,GAAI5H,MAAKjI,KAAK8M,IAAI1C,WAC/B0F,aAAezI,SAASuI,aAAaG,aAAa,GAAK,IACvDC,WAAa3I,SAASwI,WAAWE,aAAa,GAAK,GA8BvD,OA7BAH,cAAaK,WAAW,GAAGH,cAC3BD,WAAWI,WAAW,GAAGD,YAEzB9N,EAAE2G,KAAK+G,aAAaM,SAASL,YAAa,SAAS/F,KAAMqG,OACvD,GAEIC,SAFAC,WAAavG,KAAK3B,UAClBmI,OAASxG,KAAKe,cAElB,IAAIyF,QAAU3N,MAAM6I,MAAMX,eAIxB,IAHAuF,QAAUtG,KAAKyG,WAAWhD,WAC1BsB,SAASyB,WACTzB,SAASyB,QAAQF,YACVN,aAAe,GACpBjB,SAASyB,QAAQF,SAASvN,KAAK,GAC/BiN,mBAIFhG,MAAOA,KAAK0G,aACZ3B,SAASyB,UAEX,MAAOxG,KAAKM,UAAYzH,MAAMmK,IAAI1C,WAC3BN,KAAK3B,WAAakI,YACvBD,QAAUtG,KAAKyG,WAAWhD,WACtBhN,QAAQsE,YAAYgK,SAASyB,QAAQF,YACvCvB,SAASyB,QAAQF,aACnBvB,SAASyB,QAAQF,SAASvN,KAAK,GAC/BiH,KAAK2G,WAAW,MAGb5B,WAUX5N,UAAUuD,UAAU0K,eAAiB,SAASF,UAC5C,GAAItG,QAAQnF,IAAK2J,IACb8B,UAAShM,MACX0F,QAEIgI,KAAM1Q,KAAKwL,MAAMX,eACjB8F,KAAM3Q,KAAK8M,IAAIjC,gBAEnBtH,KAAO,KAAM,KAAMyL,SAAShM,IAAK,gBACjCkK,KAAOhL,EAAE0O,IAAI5Q,KAAKwL,MAAM0E,SAASlQ,KAAK8M,KAAM,SAAS5E,KAAO,MAAOA,KAAI2C,iBAEnEtK,QAAQsE,YAAYmK,SAASH,YAC/BG,SAASH,aAGX5N,UAAUZ,WAAW8C,MAAMI,IAAI4F,KAAK,KAAM,WAAYT,QAAQtF,KAAK,SAASV,MAC1ER,EAAE2G,KAAKqE,KAAM,SAAShF,KACpB,GAAIwD,KAEAnL,SAAQsE,YAAYmK,SAASH,SAAS3G,QACxC8G,SAASH,SAAS3G,SAEhB3H,QAAQsE,YAAYnC,KAAKwF,QAC3BxF,KAAKwF,QAEP,KAAK,GAAItG,GAAI,EAAQ,IAALA,EAASA,IACvB8J,KAAO9J,EAAE2L,WACL7K,KAAKwF,KAAKwD,MACZsD,SAASH,SAAS3G,KAAKwD,OACrBhJ,KAAKwF,KAAKwD,MAAM,GAChBhJ,KAAKwF,KAAKwD,MAAM,IAChBhJ,KAAKwF,KAAKwD,MAAM,IAChBhJ,KAAKwF,KAAKwD,MAAM,KAGlBsD,SAASH,SAAS3G,KAAKwD,OAAS,EAAG,EAAG,EAAG,SAcrDzK,UAAUuD,UAAUG,aAAe,SAASC,MAG1C,MAFIrE,SAAQsE,YAAYD,QACtBA,KAAO,MACFA,KAAO,WAAa5E,KAAKyO,qBAAuBzO,KAAK6Q,WAS9D5P,UAAUuD,UAAUsM,YAAc,SAASC,MACzC,GAAI/B,SACA+B,QACF/B,UACE9O,KAAM6Q,KAAKC,KACXrC,MAAOoC,KAAKE,kBACZC,KAAM,kBACNhM,OAAQ,eACRlC,IAAK+N,KAAKI,OAEPjP,EAAEC,KAAKnC,KAAK+O,UAAW,SAAS3M,GACnC,MAAOA,GAAEuM,OAASK,SAASL,UAE3BK,SAASC,MAAQhO,UAAUqF,UAAU0I,SAASL,MAAO,IACjD3O,KAAK+O,UACP/O,KAAK+O,UAAUlM,KAAKmM,UAEpBhP,KAAK+O,WAAaC,UACpBhP,KAAKkP,eAAeF,aAY1B/N,UAAUuD,UAAU4M,YAAc,SAASL,MACzC,GAAI/B,UAAW9M,EAAEC,KAAKnC,KAAK+O,UAAW,SAASC,UAC7C,MAAO9M,GAAEC,KAAK4O,KAAKM,OAAQ,SAAS1C,OAClC,MAAOA,OAAMhJ,OAASqJ,SAASL,SAGnC,OAAOpO,SAAQwI,UAAUiG,WAS3B/N,UAAUuD,UAAU8M,0BAA4B,WAC9C,MAA4B,SAArBtR,KAAKsM,MAAMC,SACfvM,KAAKoP,YACNpP,KAAK+O,WAAa/O,KAAK+O,UAAU/C,OAAS,GAU9C/K,UAAUuD,UAAU+M,aAAe,SAASC,WAC1C,GAAIjR,QAAQsE,YAAY7E,KAAKyR,YAC3BzR,KAAKyR,aAAe9L,MAAO6L,gBAExB,CACH,IAAK,GAAI5P,GAAI,EAAGA,EAAI5B,KAAKyR,WAAWzF,QAC9BhM,KAAKyR,WAAW7P,GAAG+D,OAAS6L,UADU5P,KAKxCA,GAAK5B,KAAKyR,WAAWzF,QACvBhM,KAAKyR,WAAW5O,MAAM8C,MAAO6L,YAEjC,MAAOxR,MAAKyR,WAAWzF,OAAS,GASlC/K,UAAUuD,UAAUkN,gBAAkB,SAASvB,OACzCA,MAAQ,IAAMnQ,KAAKyR,WAAWzF,OAASmE,OACzCnQ,KAAKyR,WAAWjP,OAAO2N,MAAO,IASlClP,UAAUuD,UAAUmN,OAAS,WAC3B,GAAIhP,OAAQ3C,IACZO,SAAQqC,QAAQ5C,KAAM,SAAS2F,MAAOC,KACzB,eAAPA,KAAkC,KAAVA,IAAI,UACvBjD,OAAMiD,OAGjBrF,QAAQC,OAAOR,KAAMA,KAAK4R,aAC1B5R,KAAK4R,YAAc5R,KAAKoF,OAAM,IAShCnE,UAAUuD,UAAUqN,OAAS,WAC3B,GAAkBnP,MAAdC,MAAQ3C,KAAYiD,MAAQjD,KAAK8F,IAAK9F,KAAKG,GAW/C,OATIH,MAAKkJ,cACPjG,KAAKJ,KAAK7C,KAAKkJ,cAEjBxG,MACEoP,MAAO9R,KAAK8R,MACZC,YAAa/R,KAAK+R,YAClBzF,MAAOtM,KAAKwO,UAAWxO,KAAKsM,UAGvBrL,UAAUZ,WAAW8E,KAAKlC,KAAKkG,KAAK,KAAMzG,MAAQ6J,OAAQ,oBAC9DnJ,KAAK,SAASV,MAGb,MADAC,OAAMiP,YAAcjP,MAAMyC,OAAM,GACzB1C,QASbzB,UAAUuD,UAAUO,MAAQ,WAC1B,GAAkBgD,SAAdpF,MAAQ3C,KAAeiD,MAAQjD,KAAK8F,IAAK9F,KAAKG,GAQlD,OANIH,MAAKkG,QACP6B,SAAYwE,OAAQ,SAAWvM,KAAK8H,KAAKW,eAEvCzI,KAAKkJ,cACPjG,KAAKJ,KAAK7C,KAAKkJ,cAEVjI,UAAUZ,WAAW8E,KAAKlC,KAAKkG,KAAK,KAAMnJ,KAAKoF,QAAS2C,SAC5D3E,KAAK,SAASV,MAGb,MADAC,OAAMiP,YAAcjP,MAAMyC,OAAM,GACzB1C,QAUbzB,UAAUuD,UAAUyB,QAAU,SAASJ,qBACrC,GAAIlD,OAAQ3C,IAGZA,MAAKgS,qBAAuBnM,oBAG5B7F,KAAKgS,qBAAqB5O,KAAK,SAASV,MACtCC,MAAM1C,KAAKyC,MAEXC,MAAMiP,YAAcjP,MAAMyC,SACzB,SAAS1C,MACVnC,QAAQC,OAAOmC,MAAOD,MACtBC,MAAMsP,SAAU,EAChBhR,UAAUH,KAAKoR,MAAMvP,MAAMuP,UAU/BjR,UAAUuD,UAAUY,MAAQ,WAsD1B,QAAS+M,YAAWC,YAElB,GAAItI,MAAO,GAAI7B,MAAKmK,WAAWvF,UAAU,EAAE,IAAM,IAAMuF,WAAWvF,UAAU,GAAG,KAC3EwF,MAAQvI,KAAKyG,WACb+B,QAAUxI,KAAKiG,YAKnB,OAHY,IAARsC,QAAYA,MAAQ,IAAMA,OAChB,GAAVC,UAAcA,QAAU,IAAMA,SAE3BD,MAAQ,IAAMC,QA9DvB,GAAIxG,aAiEJ,OAhEAvL,SAAQqC,QAAQ5C,KAAM,SAAS2F,MAAOC,KACzB,eAAPA,KAAkC,KAAVA,IAAI,KAC9BkG,UAAUlG,KAAOrF,QAAQgS,KAAK5M,UAKlCmG,UAAU0G,UAAY1G,UAAU9B,UAAYmI,WAAWrG,UAAU9B,WAAa,GAC9E8B,UAAU2G,QAAY3G,UAAU7B,QAAYkI,WAAWrG,UAAU7B,SAAa,GAG1EjK,KAAK8N,iBACsB,WAAzB9N,KAAKqM,OAAOgB,WAA0BrN,KAAKqM,OAAOjE,MAAMN,MAAkC,SAA1B9H,KAAKqM,OAAOjE,MAAMN,MACzD,UAAzB9H,KAAKqM,OAAOgB,WAAyBrN,KAAKqM,OAAO/D,KAAKgF,aAEjDxB,WAAUO,OAAOoB,UACxB3B,UAAUO,OAAOa,OAAUhF,IAAKlI,KAAKqM,OAAOjE,MAAMF,IAAKkF,WAAYpN,KAAKqM,OAAOjE,MAAMgF,WAAWG,cAEzFvN,KAAKqM,OAAOjE,MAAMN,YAElBgE,WAAUO,OAAOa,KAGnBlN,KAAKqM,OAAOgB,YACnBvB,UAAUO,QAAWgB,UAAWrN,KAAKqM,OAAOgB,YAE1CrN,KAAKqM,OAAOgB,UACS,SAAnBrN,KAAKqM,OAAOS,KAAkB9M,KAAKqM,OAAOuB,MAC5C9B,UAAUO,OAAOuB,MAAQ5N,KAAKqM,OAAOuB,MAAM8E,oBAAoB,KACrC,SAAnB1S,KAAKqM,OAAOS,KAAkB9M,KAAKqM,OAAOsB,MACjD7B,UAAUO,OAAOsB,MAAQ3N,KAAKqM,OAAOsB,aAE9B7B,WAAUO,OAAOuB,YACjB9B,WAAUO,OAAOsB,aAInB7B,WAAUO,OAGfrM,KAAKwO,WACHxO,KAAKsM,MAAMC,QAA+B,SAArBvM,KAAKsM,MAAMC,QAC9BvM,KAAK+O,WAAa/O,KAAK+O,UAAU/C,OAAS,IAE9ChM,KAAKsM,MAAMyC,UAAY,EACvB/O,KAAKsM,MAAMoC,UAAY,GAIzB5C,UAAUQ,SAeLR","sourcesContent":["/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @name Calendar\n * @constructor\n * @param {object} futureCalendarData - either an object literal or a promise\n */\n function Calendar(futureCalendarData) {\n // Data is immediately available\n this.init(futureCalendarData);\n if (this.name && !this.id) {\n // Create a new calendar on the server\n var newCalendarData = Calendar.$$resource.create('createFolder', this.name);\n angular.extend(this, newCalendarData);\n }\n if (this.id) {\n this.$acl = new Calendar.$$Acl('Calendar/' + this.id);\n }\n }\n\n /**\n * @memberof Calendar\n * @desc The factory we'll use to register with Angular\n * @returns the Calendar constructor\n */\n Calendar.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'Resource', 'Component', 'Acl', function($q, $timeout, $log, Settings, Resource, Component, Acl) {\n angular.extend(Calendar, {\n $q: $q,\n $timeout: $timeout,\n $log: $log,\n $$resource: new Resource(Settings.activeUser('folderURL') + 'Calendar', Settings.activeUser()),\n $Component: Component,\n $$Acl: Acl,\n activeUser: Settings.activeUser()\n });\n\n return Calendar; // return constructor\n }];\n\n /**\n * @module SOGo.SchedulerUI\n * @desc Factory registration of Calendar in Angular module.\n */\n try {\n angular.module('SOGo.SchedulerUI');\n }\n catch(e) {\n angular.module('SOGo.SchedulerUI', ['SOGo.Common']);\n }\n angular.module('SOGo.SchedulerUI')\n .factory('Calendar', Calendar.$factory);\n\n /**\n * @memberof Calendar\n * @desc Add a new calendar to the static list of calendars\n * @param {Calendar} calendar - an Calendar object instance\n */\n Calendar.$add = function(calendar) {\n // Insert new calendar at proper index\n var list, sibling, i;\n\n if (calendar.isWebCalendar)\n list = this.$webcalendars;\n else if (calendar.isSubscription)\n list = this.$subscriptions;\n else\n list = this.$calendars;\n\n sibling = _.find(list, function(o) {\n return (o.id != 'personal' &&\n o.name.localeCompare(calendar.name) === 1);\n });\n i = sibling ? _.indexOf(_.pluck(list, 'id'), sibling.id) : 1;\n list.splice(i, 0, calendar);\n };\n\n /**\n * @memberof Calendar\n * @desc Set or get the list of calendars. Will instanciate a new Calendar object for each item.\n * @param {object[]} [data] - the metadata of the calendars\n * @returns the list of calendars\n */\n Calendar.$findAll = function(data) {\n var _this = this;\n if (data) {\n this.$calendars = [];\n this.$subscriptions = [];\n this.$webcalendars = [];\n // Instanciate Calendar objects\n angular.forEach(data, function(o, i) {\n var calendar = new Calendar(o);\n if (calendar.isWebCalendar)\n _this.$webcalendars.push(calendar);\n else if (calendar.isSubscription)\n _this.$subscriptions.push(calendar);\n else\n _this.$calendars.push(calendar);\n });\n }\n return this.$calendars;\n };\n\n /**\n * @memberof Calendar\n * @desc Find a calendar among local instances (personal calendars, subscriptions and Web calendars).\n * @param {string} id - the calendar ID\n * @returns an object literal of the matching Calendar instance\n */\n Calendar.$get = function(id) {\n var calendar;\n\n calendar = _.find(Calendar.$calendars, function(o) { return o.id == id; });\n if (!calendar)\n calendar = _.find(Calendar.$subscriptions, function(o) { return o.id == id; });\n if (!calendar)\n calendar = _.find(Calendar.$webcalendars, function(o) { return o.id == id; });\n\n return calendar;\n };\n\n /**\n * @memberOf Calendar\n * @desc Subscribe to another user's calendar and add it to the list of calendars.\n * @param {string} uid - user id\n * @param {string} path - path of folder for specified user\n * @returns a promise of the HTTP query result\n */\n Calendar.$subscribe = function(uid, path) {\n var _this = this;\n return Calendar.$$resource.userResource(uid).fetch(path, 'subscribe').then(function(calendarData) {\n var calendar = new Calendar(calendarData);\n if (!_.find(_this.$subscriptions, function(o) {\n return o.id == calendarData.id;\n })) {\n Calendar.$add(calendar);\n }\n return calendar;\n });\n };\n\n /**\n * @memberOf Calendar\n * @desc Subscribe to a remote Web calendar\n * @param {string} url - URL of .ics file\n * @returns a promise of the HTTP query result\n */\n Calendar.$addWebCalendar = function(url) {\n var _this = this,\n d = Calendar.$q.defer();\n\n if (_.find(_this.$webcalendars, function(o) {\n return o.urls.webCalendarURL == url;\n })) {\n // Already subscribed\n d.reject();\n }\n else {\n Calendar.$$resource.post(null, 'addWebCalendar', { url: url }).then(function(calendarData) {\n angular.extend(calendarData, {\n isWebCalendar: true,\n isEditable: true,\n isRemote: false,\n owner: Calendar.activeUser.login,\n urls: { webCalendarURL: url }\n });\n var calendar = new Calendar(calendarData);\n Calendar.$add(calendar);\n Calendar.$$resource.fetch(calendar.id, 'reload').then(function(data) {\n // TODO: show a toast of the reload status\n Calendar.$log.debug(JSON.stringify(data, undefined, 2));\n });\n d.resolve();\n }, function() {\n d.reject();\n });\n }\n\n return d.promise;\n };\n\n /**\n * @function init\n * @memberof Calendar.prototype\n * @desc Extend instance with new data and compute additional attributes.\n * @param {object} data - attributes of calendar\n */\n Calendar.prototype.init = function(data) {\n angular.extend(this, data);\n // Add 'isOwned' and 'isSubscription' attributes based on active user (TODO: add it server-side?)\n this.isOwned = Calendar.activeUser.isSuperUser || this.owner == Calendar.activeUser.login;\n this.isSubscription = !this.isRemote && this.owner != Calendar.activeUser.login;\n };\n\n /**\n * @function getClassName\n * @memberof Calendar.prototype\n * @desc Return the calendar CSS class name based on its ID.\n * @returns a string representing the foreground CSS class name\n */\n Calendar.prototype.getClassName = function(base) {\n if (angular.isUndefined(base))\n base = 'fg';\n return base + '-folder' + this.id;\n };\n\n /**\n * @function $rename\n * @memberof Calendar.prototype\n * @desc Rename the calendar and keep the list sorted\n * @param {string} name - the new name\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$rename = function(name) {\n var i = _.indexOf(_.pluck(Calendar.$calendars, 'id'), this.id);\n this.name = name;\n Calendar.$calendars.splice(i, 1);\n Calendar.$add(this);\n return this.$save();\n };\n\n /**\n * @function $delete\n * @memberof Calendar.prototype\n * @desc Delete the calendar from the server and the static list of calendars.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$delete = function() {\n var _this = this,\n d = Calendar.$q.defer(),\n list,\n promise;\n\n if (this.isSubscription) {\n promise = Calendar.$$resource.fetch(this.id, 'unsubscribe');\n list = Calendar.$subscriptions;\n }\n else {\n promise = Calendar.$$resource.remove(this.id);\n if (this.isWebCalendar)\n list = Calendar.$webcalendars;\n else\n list = Calendar.$calendars;\n }\n\n promise.then(function() {\n var i = _.indexOf(_.pluck(list, 'id'), _this.id);\n list.splice(i, 1);\n d.resolve();\n }, function(data, status) {\n d.reject(data);\n });\n return d.promise;\n };\n\n /**\n * @function $save\n * @memberof Calendar.prototype\n * @desc Save the calendar properties to the server.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$save = function() {\n return Calendar.$$resource.save(this.id, this.$omit()).then(function(data) {\n return data;\n });\n };\n\n /**\n * @function $setActivation\n * @memberof Calendar.prototype\n * @desc Either activate or deactivate the calendar.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$setActivation = function() {\n return Calendar.$$resource.fetch(this.id, (this.active?'':'de') + 'activateFolder');\n };\n\n /**\n * @function $getComponent\n * @memberof Calendar.prototype\n * @desc Fetch a component attributes from the server.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$getComponent = function(componentId, recurrenceId) {\n return Calendar.$Component.$find(this.id, componentId, recurrenceId);\n };\n\n /**\n * @function $omit\n * @memberof Calendar.prototype\n * @desc Return a sanitized object used to send to the server.\n * @return an object literal copy of the Calendar instance\n */\n Calendar.prototype.$omit = function() {\n var calendar = {};\n angular.forEach(this, function(value, key) {\n if (key != 'constructor' &&\n key[0] != '$') {\n calendar[key] = value;\n }\n });\n return calendar;\n };\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @name Component\n * @constructor\n * @param {object} futureComponentData - either an object literal or a promise\n */\n function Component(futureComponentData) {\n // Data is immediately available\n if (typeof futureComponentData.then !== 'function') {\n this.init(futureComponentData);\n if (this.pid && !this.id) {\n // Prepare for the creation of a new component;\n // Get UID from the server.\n var newComponentData = Component.$$resource.newguid(this.pid);\n this.$unwrap(newComponentData);\n this.isNew = true;\n }\n }\n else {\n // The promise will be unwrapped first\n this.$unwrap(futureComponentData);\n }\n }\n\n /**\n * @memberof Component\n * @desc The factory we'll use to register with Angular\n * @returns the Component constructor\n */\n Component.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'Preferences', 'Gravatar', 'Resource', function($q, $timeout, $log, Settings, Preferences, Gravatar, Resource) {\n angular.extend(Component, {\n $q: $q,\n $timeout: $timeout,\n $log: $log,\n $Preferences: Preferences,\n $gravatar: Gravatar,\n $$resource: new Resource(Settings.baseURL(), Settings.activeUser()),\n timeFormat: \"%H:%M\",\n // Filter parameters common to events and tasks\n $query: { value: '', search: 'title_Category_Location' },\n // Filter paramaters specific to events\n $queryEvents: { sort: 'start', asc: 1, filterpopup: 'view_next7' },\n // Filter parameters specific to tasks\n $queryTasks: { sort: 'status', asc: 1, filterpopup: 'view_incomplete' }\n });\n Preferences.ready().then(function() {\n // Initialize filter parameters from user's settings\n if (Preferences.settings.Calendar.EventsFilterState)\n Component.$queryEvents.filterpopup = Preferences.settings.Calendar.EventsFilterState;\n if (Preferences.settings.Calendar.TasksFilterState)\n Component.$queryTasks.filterpopup = Preferences.settings.Calendar.TasksFilterState;\n if (Preferences.settings.Calendar.EventsSortingState) {\n Component.$queryEvents.sort = Preferences.settings.Calendar.EventsSortingState[0];\n Component.$queryEvents.asc = parseInt(Preferences.settings.Calendar.EventsSortingState[1]);\n }\n if (Preferences.settings.Calendar.TasksSortingState) {\n Component.$queryTasks.sort = Preferences.settings.Calendar.TasksSortingState[0];\n Component.$queryTasks.asc = parseInt(Preferences.settings.Calendar.TasksSortingState[1]);\n }\n Component.$queryTasks.show_completed = parseInt(Preferences.settings.ShowCompletedTasks);\n // Initialize categories from user's defaults\n Component.$categories = Preferences.defaults.SOGoCalendarCategoriesColors;\n // Initialize time format from user's defaults\n if (Preferences.defaults.SOGoTimeFormat) {\n Component.timeFormat = Preferences.defaults.SOGoTimeFormat;\n }\n });\n\n return Component; // return constructor\n }];\n\n /**\n * @module SOGo.SchedulerUI\n * @desc Factory registration of Component in Angular module.\n */\n try {\n angular.module('SOGo.SchedulerUI');\n }\n catch(e) {\n angular.module('SOGo.SchedulerUI', ['SOGo.Common']);\n }\n angular.module('SOGo.SchedulerUI')\n .factory('Component', Component.$factory);\n\n /**\n * @function $filter\n * @memberof Component.prototype\n * @desc Search for components matching some criterias\n * @param {string} type - either 'events' or 'tasks'\n * @param {object} [options] - additional options to the query\n * @returns a collection of Components instances\n */\n Component.$filter = function(type, options) {\n var _this = this,\n now = new Date(),\n day = now.getDate(),\n month = now.getMonth() + 1,\n year = now.getFullYear(),\n queryKey = '$query' + type.capitalize(),\n params = {\n day: '' + year + (month < 10?'0':'') + month + (day < 10?'0':'') + day,\n };\n\n return this.$Preferences.ready().then(function() {\n var futureComponentData,\n dirty = false,\n otherType;\n\n angular.extend(_this.$query, params);\n\n if (options) {\n _.each(_.keys(options), function(key) {\n // Query parameters common to events and tasks are compared\n dirty |= (_this.$query[key] && options[key] != Component.$query[key]);\n if (key == 'reload' && options[key])\n dirty = true;\n // Update either the common parameters or the type-specific parameters\n else if (angular.isDefined(_this.$query[key]))\n _this.$query[key] = options[key];\n else\n _this[queryKey][key] = options[key];\n });\n }\n\n // Perform query with both common and type-specific parameters\n futureComponentData = _this.$$resource.fetch(null, type + 'list',\n angular.extend(_this[queryKey], _this.$query));\n\n // Invalidate cached results of other type if $query has changed\n otherType = (type == 'tasks')? '$events' : '$tasks';\n if (dirty) {\n delete Component[otherType];\n Component.$log.debug('force reload of ' + otherType);\n }\n\n return _this.$unwrapCollection(type, futureComponentData);\n });\n };\n\n /**\n * @function $find\n * @desc Fetch a component from a specific calendar.\n * @param {string} calendarId - the calendar ID\n * @param {string} componentId - the component ID\n * @param {string} [occurrenceId] - the component ID\n * @see {@link Calendar.$getComponent}\n */\n Component.$find = function(calendarId, componentId, occurrenceId) {\n var futureComponentData, path = [calendarId, componentId];\n\n if (occurrenceId)\n path.push(occurrenceId);\n\n futureComponentData = this.$$resource.fetch(path.join('/'), 'view');\n\n return new Component(futureComponentData);\n };\n\n /**\n * @function filterCategories\n * @desc Search for categories matching some criterias\n * @param {string} search - the search string to match\n * @returns a collection of strings\n */\n Component.filterCategories = function(query) {\n var re = new RegExp(query, 'i');\n return _.filter(_.keys(Component.$categories), function(category) {\n return category.search(re) != -1;\n });\n };\n\n /**\n * @function saveSelectedList\n * @desc Save to the user's settings the currently selected list.\n * @param {string} componentType - either \"events\" or \"tasks\"\n * @returns a promise of the HTTP operation\n */\n Component.saveSelectedList = function(componentType) {\n return this.$$resource.post(null, 'saveSelectedList', { list: componentType + 'ListView' });\n };\n\n /**\n * @function $eventsBlocksForView\n * @desc Events blocks for a specific week\n * @param {string} view - Either 'day' or 'week'\n * @param {Date} type - Date of any day of the desired period\n * @returns a promise of a collection of objects describing the events blocks\n */\n Component.$eventsBlocksForView = function(view, date) {\n var viewAction, startDate, endDate, params;\n\n if (view == 'day') {\n viewAction = 'dayView';\n startDate = endDate = date;\n }\n else if (view == 'week') {\n viewAction = 'weekView';\n startDate = date.beginOfWeek();\n endDate = new Date();\n endDate.setTime(startDate.getTime());\n endDate.addDays(6);\n }\n else if (view == 'month') {\n viewAction = 'monthView';\n startDate = date;\n startDate.setDate(1);\n startDate = startDate.beginOfWeek();\n endDate = new Date();\n endDate.setTime(startDate.getTime());\n endDate.setMonth(endDate.getMonth() + 1);\n endDate.addDays(-1);\n endDate = endDate.endOfWeek();\n }\n return this.$eventsBlocks(viewAction, startDate, endDate);\n };\n\n /**\n * @function $eventsBlocks\n * @desc Events blocks for a specific view and period\n * @param {string} view - Either 'day' or 'week'\n * @param {Date} startDate - period's start date\n * @param {Date} endDate - period's end date\n * @returns a promise of a collection of objects describing the events blocks\n */\n Component.$eventsBlocks = function(view, startDate, endDate) {\n var params, futureComponentData, i,\n deferred = Component.$q.defer();\n\n params = { view: view.toLowerCase(), sd: startDate.getDayString(), ed: endDate.getDayString() };\n Component.$log.debug('eventsblocks ' + JSON.stringify(params, undefined, 2));\n futureComponentData = this.$$resource.fetch(null, 'eventsblocks', params);\n futureComponentData.then(function(data) {\n Component.$timeout(function() {\n var components = [], blocks = {};\n\n // Instantiate Component objects\n _.reduce(data.events, function(objects, eventData, i) {\n var componentData = _.object(data.eventsFields, eventData),\n start = new Date(componentData.c_startdate * 1000);\n componentData.hour = start.getHourString();\n objects.push(new Component(componentData));\n return objects;\n }, components);\n\n // Associate Component objects to blocks positions\n _.each(_.flatten(data.blocks), function(block) {\n block.component = components[block.nbr];\n });\n\n // Convert array of blocks to object with days as keys\n for (i = 0; i < data.blocks.length; i++) {\n blocks[startDate.getDayString()] = data.blocks[i];\n startDate.addDays(1);\n }\n\n Component.$log.debug('blocks ready (' + _.keys(blocks).length + ')');\n\n // Save the blocks to the object model\n Component.$blocks = blocks;\n\n deferred.resolve(blocks);\n });\n }, deferred.reject);\n\n return deferred.promise;\n };\n\n /**\n * @function $unwrapCollection\n * @desc Unwrap a promise and instanciate new Component objects using received data.\n * @param {string} type - either 'events' or 'tasks'\n * @param {promise} futureComponentData - a promise of the components' metadata\n * @returns a promise of the HTTP operation\n */\n Component.$unwrapCollection = function(type, futureComponentData) {\n var _this = this,\n components = [];\n\n return futureComponentData.then(function(data) {\n return Component.$timeout(function() {\n var fields = _.invoke(data.fields, 'toLowerCase');\n\n // Instanciate Component objects\n _.reduce(data[type], function(components, componentData, i) {\n var data = _.object(fields, componentData);\n components.push(new Component(data));\n return components;\n }, components);\n\n Component.$log.debug('list of ' + type + ' ready (' + components.length + ')');\n\n // Save the list of components to the object model\n Component['$' + type] = components;\n\n return components;\n });\n });\n };\n\n /**\n * @function init\n * @memberof Component.prototype\n * @desc Extend instance with required attributes and new data.\n * @param {object} data - attributes of component\n */\n Component.prototype.init = function(data) {\n var _this = this;\n\n this.categories = [];\n this.repeat = {};\n this.alarm = { action: 'display', quantity: 5, unit: 'MINUTES', reference: 'BEFORE', relation: 'START' };\n this.status = 'not-specified';\n angular.extend(this, data);\n\n Component.$Preferences.ready().then(function() {\n var type = (_this.type == 'appointment')? 'Events' : 'Tasks';\n\n // Set default values from user's defaults\n _this.classification = _this.classification ||\n Component.$Preferences.defaults['SOGoCalendar' + type + 'DefaultClassification'].toLowerCase();\n });\n\n if (this.startDate)\n this.start = new Date(this.startDate.substring(0,10) + ' ' + this.startDate.substring(11,16));\n if (this.endDate)\n this.end = new Date(this.endDate.substring(0,10) + ' ' + this.endDate.substring(11,16));\n if (this.dueDate)\n this.due = new Date(this.dueDate.substring(0,10) + ' ' + this.dueDate.substring(11,16));\n\n // Parse recurrence rule definition and initialize default values\n this.$isRecurrent = angular.isDefined(data.repeat);\n if (this.repeat.days) {\n var byDayMask = _.find(this.repeat.days, function(o) {\n return angular.isDefined(o.occurrence);\n });\n if (byDayMask)\n if (this.repeat.frequency == 'yearly')\n this.repeat.year = { byday: true };\n this.repeat.month = {\n type: 'byday',\n occurrence: byDayMask.occurrence.toString(),\n day: byDayMask.day\n };\n }\n else {\n this.repeat.days = [];\n }\n if (angular.isUndefined(this.repeat.frequency))\n this.repeat.frequency = 'never';\n if (angular.isUndefined(this.repeat.interval))\n this.repeat.interval = 1;\n if (angular.isUndefined(this.repeat.month))\n this.repeat.month = { occurrence: '1', day: 'SU', type: 'bymonthday' };\n if (angular.isUndefined(this.repeat.monthdays))\n this.repeat.monthdays = [];\n if (angular.isUndefined(this.repeat.months))\n this.repeat.months = [];\n if (angular.isUndefined(this.repeat.year))\n this.repeat.year = {};\n if (this.repeat.count)\n this.repeat.end = 'count';\n else if (this.repeat.until) {\n this.repeat.end = 'until';\n this.repeat.until = this.repeat.until.substring(0,10).asDate();\n }\n else\n this.repeat.end = 'never';\n this.$hasCustomRepeat = this.hasCustomRepeat();\n\n if (this.isNew) {\n // Set default alarm\n Component.$Preferences.ready().then(function() {\n var units = { M: 'MINUTES', H: 'HOURS', D: 'DAYS', W: 'WEEKS' };\n var match = /-PT?([0-9]+)([MHDW])/.exec(Component.$Preferences.defaults.SOGoCalendarDefaultReminder);\n if (match) {\n _this.$hasAlarm = true;\n _this.alarm.quantity = parseInt(match[1]);\n _this.alarm.unit = units[match[2]];\n }\n });\n }\n else {\n this.$hasAlarm = angular.isDefined(data.alarm);\n }\n\n // Allow the component to be moved to a different calendar\n this.destinationCalendar = this.pid;\n\n if (this.organizer && this.organizer.email) {\n this.organizer.$image = Component.$gravatar(this.organizer.email, 32);\n }\n\n // Load freebusy of attendees\n this.freebusy = this.updateFreeBusyCoverage();\n\n if (this.attendees) {\n _.each(this.attendees, function(attendee) {\n attendee.image = Component.$gravatar(attendee.email, 32);\n _this.updateFreeBusy(attendee);\n });\n }\n };\n\n /**\n * @function hasCustomRepeat\n * @memberof Component.prototype\n * @desc Check if the component has a custom recurrence rule.\n * @returns true if the recurrence rule requires the full recurrence editor\n */\n Component.prototype.hasCustomRepeat = function() {\n var b = angular.isDefined(this.repeat) &&\n (this.repeat.interval > 1 ||\n this.repeat.days && this.repeat.days.length > 0 ||\n this.repeat.monthdays && this.repeat.monthdays.length > 0 ||\n this.repeat.months && this.repeat.months.length > 0);\n return b;\n };\n\n /**\n * @function isEditable\n * @memberof Component.prototype\n * @desc Check if the component is editable and not an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isEditable = function() {\n return (!this.occurrenceId && !this.isReadOnly);\n };\n\n /**\n * @function isEditableOccurrence\n * @memberof Component.prototype\n * @desc Check if the component is editable and an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isEditableOccurrence = function() {\n return (this.occurrenceId && !this.isReadOnly);\n };\n\n /**\n * @function isInvitation\n * @memberof Component.prototype\n * @desc Check if the component an invitation and not an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isInvitation = function() {\n return (!this.occurrenceId && this.userHasRSVP);\n };\n\n /**\n * @function isInvitationOccurrence\n * @memberof Component.prototype\n * @desc Check if the component an invitation and an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isInvitationOccurrence = function() {\n return (this.occurrenceId && this.userHasRSVP);\n };\n\n /**\n * @function isReadOnly\n * @memberof Component.prototype\n * @desc Check if the component is not editable and not an invitation\n * @returns true or false\n */\n Component.prototype.isReadOnly = function() {\n return (this.isReadOnly && !this.userHasRSVP);\n };\n\n /**\n * @function enablePercentComplete\n * @memberof Component.prototype\n * @desc Check if the percent completion should be enabled with respect to the\n * component's type and status.\n * @returns true if the percent completion should be displayed\n */\n Component.prototype.enablePercentComplete = function() {\n return (this.component = 'vtodo' &&\n this.status != 'not-specified' &&\n this.status != 'cancelled');\n };\n\n /**\n * @function coversFreeBusy\n * @memberof Component.prototype\n * @desc Check if a specific quarter matches the component's period\n * @returns true if the quarter covers the component's period\n */\n Component.prototype.coversFreeBusy = function(day, hour, quarter) {\n var b = (angular.isDefined(this.freebusy[day]) &&\n angular.isDefined(this.freebusy[day][hour]) &&\n this.freebusy[day][hour][quarter] == 1);\n return b;\n };\n\n /**\n * @function updateFreeBusyCoverage\n * @memberof Component.prototype\n * @desc Build a 15-minute-based representation of the component's period.\n * @returns an object literal hashed by days and hours and arrays of four 1's and 0's\n */\n Component.prototype.updateFreeBusyCoverage = function() {\n var _this = this, freebusy = {};\n\n if (this.start && this.end) {\n var roundedStart = new Date(this.start.getTime()),\n roundedEnd = new Date(this.end.getTime()),\n startQuarter = parseInt(roundedStart.getMinutes()/15 + 0.5),\n endQuarter = parseInt(roundedEnd.getMinutes()/15 + 0.5);\n roundedStart.setMinutes(15*startQuarter);\n roundedEnd.setMinutes(15*endQuarter);\n\n _.each(roundedStart.daysUpTo(roundedEnd), function(date, index) {\n var currentDay = date.getDate(),\n dayKey = date.getDayString(),\n hourKey;\n if (dayKey == _this.start.getDayString()) {\n hourKey = date.getHours().toString();\n freebusy[dayKey] = {};\n freebusy[dayKey][hourKey] = [];\n while (startQuarter > 0) {\n freebusy[dayKey][hourKey].push(0);\n startQuarter--;\n }\n }\n else {\n date = date.beginOfDay();\n freebusy[dayKey] = {};\n }\n while (date.getTime() < _this.end.getTime() &&\n date.getDate() == currentDay) {\n hourKey = date.getHours().toString();\n if (angular.isUndefined(freebusy[dayKey][hourKey]))\n freebusy[dayKey][hourKey] = [];\n freebusy[dayKey][hourKey].push(1);\n date.addMinutes(15);\n }\n });\n return freebusy;\n }\n };\n\n /**\n * @function updateFreeBusy\n * @memberof Component.prototype\n * @desc Update the freebusy information for the component's period for a specific attendee.\n * @param {Object} card - an Card object instance of the attendee\n */\n Component.prototype.updateFreeBusy = function(attendee) {\n var params, url, days;\n if (attendee.uid) {\n params =\n {\n sday: this.start.getDayString(),\n eday: this.end.getDayString()\n };\n url = ['..', '..', attendee.uid, 'freebusy.ifb'];\n days = _.map(this.start.daysUpTo(this.end), function(day) { return day.getDayString(); });\n\n if (angular.isUndefined(attendee.freebusy))\n attendee.freebusy = {};\n\n // Fetch FreeBusy information\n Component.$$resource.fetch(url.join('/'), 'ajaxRead', params).then(function(data) {\n _.each(days, function(day) {\n var hour;\n\n if (angular.isUndefined(attendee.freebusy[day]))\n attendee.freebusy[day] = {};\n\n if (angular.isUndefined(data[day]))\n data[day] = {};\n\n for (var i = 0; i <= 23; i++) {\n hour = i.toString();\n if (data[day][hour])\n attendee.freebusy[day][hour] = [\n data[day][hour][\"0\"],\n data[day][hour][\"15\"],\n data[day][hour][\"30\"],\n data[day][hour][\"45\"]\n ];\n else\n attendee.freebusy[day][hour] = [0, 0, 0, 0];\n }\n });\n });\n }\n };\n\n /**\n * @function getClassName\n * @memberof Component.prototype\n * @desc Return the component CSS class name based on its container (calendar) ID.\n * @param {string} [base] - the prefix to add to the class name (defaults to \"fg\")\n * @returns a string representing the foreground CSS class name\n */\n Component.prototype.getClassName = function(base) {\n if (angular.isUndefined(base))\n base = 'fg';\n return base + '-folder' + (this.destinationCalendar || this.c_folder);\n };\n\n /**\n * @function addAttendee\n * @memberof Component.prototype\n * @desc Add an attendee and fetch his freebusy info.\n * @param {Object} card - an Card object instance to be added to the attendees list\n */\n Component.prototype.addAttendee = function(card) {\n var attendee, url, params;\n if (card) {\n attendee = {\n name: card.c_cn,\n email: card.$preferredEmail(),\n role: 'req-participant',\n status: 'needs-action',\n uid: card.c_uid\n };\n if (!_.find(this.attendees, function(o) {\n return o.email == attendee.email;\n })) {\n attendee.image = Component.$gravatar(attendee.email, 32);\n if (this.attendees)\n this.attendees.push(attendee);\n else\n this.attendees = [attendee];\n this.updateFreeBusy(attendee);\n }\n }\n };\n\n /**\n * @function hasAttendee\n * @memberof Component.prototype\n * @desc Verify if one of the email addresses of a Card instance matches an attendee.\n * @param {Object} card - an Card object instance\n * @returns true if the Card matches an attendee\n */\n Component.prototype.hasAttendee = function(card) {\n var attendee = _.find(this.attendees, function(attendee) {\n return _.find(card.emails, function(email) {\n return email.value == attendee.email;\n });\n });\n return angular.isDefined(attendee);\n };\n\n /**\n * @function canRemindAttendeesByEmail\n * @memberof Component.prototype\n * @desc Verify if the component's reminder must be send by email and if it has at least one attendee.\n * @returns true if attendees can receive a reminder by email\n */\n Component.prototype.canRemindAttendeesByEmail = function() {\n return this.alarm.action == 'email' &&\n !this.isReadOnly &&\n this.attendees && this.attendees.length > 0;\n };\n\n /**\n * @function addAttachUrl\n * @memberof Component.prototype\n * @desc Add a new attach URL if not already defined\n * @param {string} attachUrl - the URL\n * @returns the number of values in the list of attach URLs\n */\n Component.prototype.addAttachUrl = function(attachUrl) {\n if (angular.isUndefined(this.attachUrls)) {\n this.attachUrls = [{value: attachUrl}];\n }\n else {\n for (var i = 0; i < this.attachUrls.length; i++) {\n if (this.attachUrls[i].value == attachUrl) {\n break;\n }\n }\n if (i == this.attachUrls.length)\n this.attachUrls.push({value: attachUrl});\n }\n return this.attachUrls.length - 1;\n };\n\n /**\n * @function deleteAttachUrl\n * @memberof Component.prototype\n * @desc Remove an attach URL\n * @param {number} index - the URL index in the list of attach URLs\n */\n Component.prototype.deleteAttachUrl = function(index) {\n if (index > -1 && this.attachUrls.length > index) {\n this.attachUrls.splice(index, 1);\n }\n };\n\n /**\n * @function $reset\n * @memberof Component.prototype\n * @desc Reset the original state the component's data.\n */\n Component.prototype.$reset = function() {\n var _this = this;\n angular.forEach(this, function(value, key) {\n if (key != 'constructor' && key[0] != '$') {\n delete _this[key];\n }\n });\n angular.extend(this, this.$shadowData);\n this.$shadowData = this.$omit(true);\n };\n\n /**\n * @function reply\n * @memberof Component.prototype\n * @desc Reply to an invitation.\n * @returns a promise of the HTTP operation\n */\n Component.prototype.$reply = function() {\n var _this = this, data, path = [this.pid, this.id];\n\n if (this.occurrenceId)\n path.push(this.occurrenceId);\n\n data = {\n reply: this.reply,\n delegatedTo: this.delegatedTo,\n alarm: this.$hasAlarm? this.alarm : {}\n };\n\n return Component.$$resource.save(path.join('/'), data, { action: 'rsvpAppointment' })\n .then(function(data) {\n // Make a copy of the data for an eventual reset\n _this.$shadowData = _this.$omit(true);\n return data;\n });\n };\n\n /**\n * @function $save\n * @memberof Component.prototype\n * @desc Save the component to the server.\n */\n Component.prototype.$save = function() {\n var _this = this, options, path = [this.pid, this.id];\n\n if (this.isNew)\n options = { action: 'saveAs' + this.type.capitalize() };\n\n if (this.occurrenceId)\n path.push(this.occurrenceId);\n\n return Component.$$resource.save(path.join('/'), this.$omit(), options)\n .then(function(data) {\n // Make a copy of the data for an eventual reset\n _this.$shadowData = _this.$omit(true);\n return data;\n });\n };\n\n /**\n * @function $unwrap\n * @memberof Component.prototype\n * @desc Unwrap a promise.\n * @param {promise} futureComponentData - a promise of some of the Component's data\n */\n Component.prototype.$unwrap = function(futureComponentData) {\n var _this = this;\n\n // Expose the promise\n this.$futureComponentData = futureComponentData;\n\n // Resolve the promise\n this.$futureComponentData.then(function(data) {\n _this.init(data);\n // Make a copy of the data for an eventual reset\n _this.$shadowData = _this.$omit();\n }, function(data) {\n angular.extend(_this, data);\n _this.isError = true;\n Component.$log.error(_this.error);\n });\n };\n\n /**\n * @function $omit\n * @memberof Component.prototype\n * @desc Return a sanitized object used to send to the server.\n * @return an object literal copy of the Component instance\n */\n Component.prototype.$omit = function() {\n var component = {}, date;\n angular.forEach(this, function(value, key) {\n if (key != 'constructor' && key[0] != '$') {\n component[key] = angular.copy(value);\n }\n });\n\n // Format times\n component.startTime = component.startDate ? formatTime(component.startDate) : '';\n component.endTime = component.endDate ? formatTime(component.endDate) : '';\n\n // Update recurrence definition depending on selections\n if (this.$hasCustomRepeat) {\n if (this.repeat.frequency == 'monthly' && this.repeat.month.type && this.repeat.month.type == 'byday' ||\n this.repeat.frequency == 'yearly' && this.repeat.year.byday) {\n // BYDAY mask for a monthly or yearly recurrence\n delete component.repeat.monthdays;\n component.repeat.days = [{ day: this.repeat.month.day, occurrence: this.repeat.month.occurrence.toString() }];\n }\n else if (this.repeat.month.type) {\n // montly recurrence by month days or yearly by month\n delete component.repeat.days;\n }\n }\n else if (this.repeat.frequency) {\n component.repeat = { frequency: this.repeat.frequency };\n }\n if (this.repeat.frequency) {\n if (this.repeat.end == 'until' && this.repeat.until)\n component.repeat.until = this.repeat.until.stringWithSeparator('-');\n else if (this.repeat.end == 'count' && this.repeat.count)\n component.repeat.count = this.repeat.count;\n else {\n delete component.repeat.until;\n delete component.repeat.count;\n }\n }\n else {\n delete component.repeat;\n }\n\n if (this.$hasAlarm) {\n if (this.alarm.action && this.alarm.action == 'email' &&\n !(this.attendees && this.attendees.length > 0)) {\n // No attendees; email reminder must be sent to organizer only\n this.alarm.attendees = 0;\n this.alarm.organizer = 1;\n }\n }\n else {\n component.alarm = {};\n }\n\n function formatTime(dateString) {\n // YYYY-MM-DDTHH:MM-ZZ:00 => YYYY-MM-DD HH:MM\n var date = new Date(dateString.substring(0,10) + ' ' + dateString.substring(11,16)),\n hours = date.getHours(),\n minutes = date.getMinutes();\n\n if (hours < 10) hours = '0' + hours;\n if (minutes < 10) minutes = '0' + minutes;\n\n return hours + ':' + minutes;\n }\n\n return component;\n };\n\n})();\n"]}