# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb is free software: you can redistribute it and/or modify it under the# terms of the GNU Lesser General Public License as published by the Free# Software Foundation, either version 2.1 of the License, or (at your option)# any later version.## CubicWeb is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with CubicWeb. If not, see <http://www.gnu.org/licenses/>."""html calendar views"""__docformat__="restructuredtext en"_=unicodeimportcopyfromdatetimeimporttimedeltafromlogilab.mtconverterimportxml_escapefromlogilab.common.dateimporttodatetimefromcubicweb.utilsimportjson_dumps,make_uidfromcubicweb.interfacesimportICalendarablefromcubicweb.selectorsimportimplements,adaptablefromcubicweb.viewimportEntityView,EntityAdapter,implements_adapter_compat# useful constants & functions ################################################ONEDAY=timedelta(1)WEEKDAYS=(_("monday"),_("tuesday"),_("wednesday"),_("thursday"),_("friday"),_("saturday"),_("sunday"))MONTHNAMES=(_('january'),_('february'),_('march'),_('april'),_('may'),_('june'),_('july'),_('august'),_('september'),_('october'),_('november'),_('december'))classICalendarableAdapter(EntityAdapter):__needs_bw_compat__=True__regid__='ICalendarable'__select__=implements(ICalendarable,warn=False)# XXX for bw compat, should be abstract@property@implements_adapter_compat('ICalendarable')defstart(self):"""return start date"""raiseNotImplementedError@property@implements_adapter_compat('ICalendarable')defstop(self):"""return stop date"""raiseNotImplementedError# Calendar views ##############################################################try:fromvobjectimportiCalendarclassiCalView(EntityView):"""A calendar view that generates a iCalendar file (RFC 2445) Does apply to ICalendarable compatible entities """__select__=adaptable('ICalendarable')paginable=Falsecontent_type='text/calendar'title=_('iCalendar')templatable=False__regid__='ical'defcall(self):ical=iCalendar()foriinrange(len(self.cw_rset.rows)):task=self.cw_rset.complete_entity(i,0)event=ical.add('vevent')event.add('summary').value=task.dc_title()event.add('description').value=task.dc_description()icalendarable=task.cw_adapt_to('ICalendarable')ificalendarable.start:event.add('dtstart').value=icalendarable.startificalendarable.stop:event.add('dtend').value=icalendarable.stopbuff=ical.serialize()ifnotisinstance(buff,unicode):buff=unicode(buff,self._cw.encoding)self.w(buff)exceptImportError:passclasshCalView(EntityView):"""A calendar view that generates a hCalendar file Does apply to ICalendarable compatible entities """__regid__='hcal'__select__=adaptable('ICalendarable')paginable=Falsetitle=_('hCalendar')#templatable = Falsedefcall(self):self.w(u'<div class="hcalendar">')foriinrange(len(self.cw_rset.rows)):task=self.cw_rset.complete_entity(i,0)self.w(u'<div class="vevent">')self.w(u'<h3 class="summary">%s</h3>'%xml_escape(task.dc_title()))self.w(u'<div class="description">%s</div>'%task.dc_description(format='text/html'))icalendarable=task.cw_adapt_to('ICalendarable')ificalendarable.start:self.w(u'<abbr class="dtstart" title="%s">%s</abbr>'%(icalendarable.start.isoformat(),self._cw.format_date(icalendarable.start)))ificalendarable.stop:self.w(u'<abbr class="dtstop" title="%s">%s</abbr>'%(icalendarable.stop.isoformat(),self._cw.format_date(icalendarable.stop)))self.w(u'</div>')self.w(u'</div>')classCalendarItemView(EntityView):__regid__='calendaritem'defcell_call(self,row,col,dates=False):task=self.cw_rset.complete_entity(row,0)task.view('oneline',w=self.w)ifdates:icalendarable=task.cw_adapt_to('ICalendarable')ificalendarable.startandicalendarable.stop:self.w('<br/> %s'%self._cw._('from %(date)s')%{'date':self._cw.format_date(icalendarable.start)})self.w('<br/> %s'%self._cw._('to %(date)s')%{'date':self._cw.format_date(icalendarable.stop)})else:self.w('<br/>%s'%self._cw.format_date(icalendarable.startoricalendarable.stop))class_TaskEntry(object):def__init__(self,task,color,index=0):self.task=taskself.color=colorself.index=indexself.length=1icalendarable=task.cw_adapt_to('ICalendarable')self.start=icalendarable.startself.stop=icalendarable.stopdefin_working_hours(self):"""predicate returning True is the task is in working hours"""iftodatetime(self.start).hour>7andtodatetime(self.stop).hour<20:returnTruereturnFalsedefis_one_day_task(self):returnself.startandself.stopandself.start.isocalendar()==self.stop.isocalendar()classCalendarView(EntityView):__regid__='calendar'__select__=adaptable('ICalendarable')paginable=Falsetitle=_('calendar')fullcalendar_options={'firstDay':1,'firstHour':8,'defaultView':'month','editable':True,'header':{'left':'prev,next today','center':'title','right':'month,agendaWeek,agendaDay',},}defcall(self):self._cw.demote_to_html()self._cw.add_css(('fullcalendar.css','cubicweb.calendar.css'))self._cw.add_js(('jquery.ui.js','fullcalendar.min.js','jquery.qtip.min.js','fullcalendar.locale.js'))self.calendar_id='cal'+make_uid('uid')self.add_onload()# write calendar div to load jquery fullcalendar objectself.w(u'<div id="%s"></div>'%self.calendar_id)defadd_onload(self):fullcalendar_options=self.fullcalendar_options.copy()fullcalendar_options['events']=self.get_events()# i18n# js callback to add a tooltip and to put html in event's titlejs=""" var options = $.fullCalendar.regional('%s', %s); options.eventRender = function(event, $element) { // add a tooltip for each event var div = '<div class="tooltip">'+ event.description+ '</div>'; $element.append(div); // allow to have html tags in event's title $element.find('span.fc-event-title').html($element.find('span.fc-event-title').text()); }; $("#%s").fullCalendar(options); """#"self._cw.add_onload(js%(self._cw.lang,json_dumps(fullcalendar_options),self.calendar_id))defget_events(self):events=[]forentityinself.cw_rset.entities():icalendarable=entity.cw_adapt_to('ICalendarable')ifnot(icalendarable.startandicalendarable.stop):continuestart_date=icalendarable.startoricalendarable.stopevent={'eid':entity.eid,'title':entity.view('calendaritem'),'url':xml_escape(entity.absolute_url()),'className':'calevent','description':entity.view('tooltip'),}event['start']=start_date.strftime('%Y-%m-%dT%H:%M')event['allDay']=Trueificalendarable.stop:event['end']=icalendarable.stop.strftime('%Y-%m-%dT%H:%M')event['allDay']=Falseevents.append(event)returneventsclassOneMonthCal(CalendarView):__regid__='onemonthcal'title=_('one month')classOneWeekCal(CalendarView):__regid__='oneweekcal'title=_('one week')fullcalendar_options=CalendarView.fullcalendar_options.copy()fullcalendar_options['defaultView']='agendaWeek'