[gen] Calendar field: added the possibility to define a start and or end date for defining a specific date range; also added param 'defaultDate' (by default=now): when the calendar is shown for the 1st time, it shows the month where this date is included.

This commit is contained in:
Gaetan Delannay 2012-10-13 18:09:42 +02:00
parent 856cda9031
commit 614ce576af
2 changed files with 96 additions and 42 deletions

View file

@ -17,7 +17,8 @@ class Calendar(Type):
specificWritePermission=False, width=None, height=300, specificWritePermission=False, width=None, height=300,
colspan=1, master=None, masterValue=None, focus=False, colspan=1, master=None, masterValue=None, focus=False,
mapping=None, label=None, maxEventLength=50, mapping=None, label=None, maxEventLength=50,
otherCalendars=None): otherCalendars=None, startDate=None, endDate=None,
defaultDate=None):
Type.__init__(self, validator, (0,1), None, default, False, False, Type.__init__(self, validator, (0,1), None, default, False, False,
show, page, group, layouts, move, False, False, show, page, group, layouts, move, False, False,
specificReadPermission, specificWritePermission, specificReadPermission, specificWritePermission,
@ -51,6 +52,19 @@ class Calendar(Type):
# leading "#" when relevant) into which events of the calendar must # leading "#" when relevant) into which events of the calendar must
# appear. # appear.
self.otherCalendars = otherCalendars self.otherCalendars = otherCalendars
# One may limit event encoding and viewing to a limited period of time,
# via p_startDate and p_endDate. Those parameters, if given, must hold
# methods accepting no arg and returning a Zope DateTime instance.
self.startDate = startDate
# Beware: specify an end date with an hour like
# DateTime('2012/10/13 23:59:59') to avoid surprises.
self.endDate = endDate
# If a default date is specified, it must be a method accepting no arg
# and returning a DateTime instance. As soon as the calendar is shown,
# the month where this date is included will be shown. If not default
# date is specified, it will be 'now' at the moment the calendar is
# shown.
self.defaultDate = defaultDate
def getSiblingMonth(self, month, prevNext): def getSiblingMonth(self, month, prevNext):
'''Gets the next or previous month (depending of p_prevNext) relative '''Gets the next or previous month (depending of p_prevNext) relative
@ -171,6 +185,22 @@ class Calendar(Type):
else: else:
return obj.translate('%s_event_%s' % (self.labelId, eventType)) return obj.translate('%s_event_%s' % (self.labelId, eventType))
def getStartDate(self, obj):
'''Get the start date for this calendar if defined.'''
if self.startDate: return self.startDate(obj.appy())
def getEndDate(self, obj):
'''Get the end date for this calendar if defined.'''
if self.endDate: return self.endDate(obj.appy())
def getDefaultDate(self, obj):
'''Get the default date that must appear as soon as the calendar is
shown.'''
if self.defaultDate:
return self.defaultDate(obj.appy())
else:
return DateTime() # Now
def createEvent(self, obj, date, handleEventSpan=True): def createEvent(self, obj, date, handleEventSpan=True):
'''Create a new event in the calendar, at some p_date (day). If '''Create a new event in the calendar, at some p_date (day). If
p_handleEventSpan is True, we will use rq["eventSpan"] and also p_handleEventSpan is True, we will use rq["eventSpan"] and also

View file

@ -5,13 +5,16 @@
month request/month; month request/month;
monthDayOne python: DateTime('%s/01' % month); monthDayOne python: DateTime('%s/01' % month);
today python: DateTime('00:00'); today python: DateTime('00:00');
todayMonth python: today.strftime('%Y/%m'); defaultDate python: contextObj.callField(fieldName, 'getDefaultDate', contextObj);
defaultDateMonth python: defaultDate.strftime('%Y/%m');
grid python: contextObj.callField(fieldName, 'getMonthGrid', month); grid python: contextObj.callField(fieldName, 'getMonthGrid', month);
previousMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'previous'); previousMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'previous');
nextMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'next'); nextMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'next');
widget python: contextObj.getAppyType(fieldName, asDict=True); widget python: contextObj.getAppyType(fieldName, asDict=True);
mayEdit python: contextObj.allows(widget['writePermission']); mayEdit python: contextObj.allows(widget['writePermission']);
objUrl contextObj/absolute_url; objUrl contextObj/absolute_url;
startDate python: contextObj.callField(fieldName, 'getStartDate', contextObj);
endDate python: contextObj.callField(fieldName, 'getEndDate', contextObj);
otherCalendars python: contextObj.callField(fieldName, 'getOtherCalendars', contextObj);" otherCalendars python: contextObj.callField(fieldName, 'getOtherCalendars', contextObj);"
tal:attributes="id ajaxHookId"> tal:attributes="id ajaxHookId">
@ -19,15 +22,25 @@
tal:content="python: 'var %s_maxEventLength = %d;' % (fieldName, widget['maxEventLength'])"> tal:content="python: 'var %s_maxEventLength = %d;' % (fieldName, widget['maxEventLength'])">
</script> </script>
<tal:comment replace="nothing">Month chooser</tal:comment> <tal:comment replace="nothing">Month chooser</tal:comment>
<div style="margin-bottom: 5px"> <div style="margin-bottom: 5px"
<img style="cursor:pointer" tal:define="fmt python: '%Y/%m/%d';
goBack python: not startDate or (startDate.strftime(fmt) &lt; grid[0][0].strftime(fmt));
goForward python: not endDate or (endDate.strftime(fmt) &gt; grid[-1][-1].strftime(fmt))">
<tal:comment replace="nothing">Go to the previous month</tal:comment>
<img style="cursor:pointer" tal:condition="goBack"
tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png; tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png;
onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,previousMonth)"/> onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,previousMonth)"/>
<tal:comment replace="nothing">Go back to the default date</tal:comment>
<tal:button condition="python: goBack or goForward">
<input type="button" <input type="button"
tal:attributes="value python: _('today'); tal:define="fmt python: '%Y/%m';
onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,todayMonth); label python: test(defaultDate.strftime(fmt) == today.strftime(fmt), 'today', 'goto_source')"
disabled monthDayOne/isCurrentMonth"/> tal:attributes="value python: _(label);
<img style="cursor:pointer" onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,defaultDateMonth);
disabled python: defaultDate.strftime(fmt) == monthDayOne.strftime(fmt)"/>
</tal:button>
<tal:comment replace="nothing">Go to the next month</tal:comment>
<img style="cursor:pointer" tal:condition="goForward"
tal:attributes="src string: $appUrl/ui/arrowRightSimple.png; tal:attributes="src string: $appUrl/ui/arrowRightSimple.png;
onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,nextMonth)"/> onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,nextMonth)"/>
<span tal:content="python: _('month_%s' % monthDayOne.aMonth())"></span> <span tal:content="python: _('month_%s' % monthDayOne.aMonth())"></span>
@ -46,6 +59,15 @@
<tal:comment replace="nothing">The calendar in itself</tal:comment> <tal:comment replace="nothing">The calendar in itself</tal:comment>
<tr tal:repeat="row grid" valign="top" tal:attributes="height rowHeight"> <tr tal:repeat="row grid" valign="top" tal:attributes="height rowHeight">
<tal:cell repeat="date row"> <tal:cell repeat="date row">
<tal:cel define="tooEarly python: startDate and (date &lt; startDate);
tooLate python: endDate and not tooEarly and (date &gt; endDate);
inRange python: not tooEarly and not tooLate">
<tal:comment replace="nothing">Dump an empty cell if we are out of the supported date range</tal:comment>
<td tal:condition="not: inRange"
tal:attributes="class python: test(date &lt; today, 'even', 'odd');">
</td>
<tal:comment replace="nothing">Dump a normal cell if we are in range</tal:comment>
<tal:td condition="inRange">
<td tal:define="events python: contextObj.callField(fieldName, 'getEventsAt', contextObj, date); <td tal:define="events python: contextObj.callField(fieldName, 'getEventsAt', contextObj, date);
spansDays python: contextObj.callField(fieldName, 'hasEventsAt', contextObj, date+1, events); spansDays python: contextObj.callField(fieldName, 'hasEventsAt', contextObj, date+1, events);
mayCreate python: mayEdit and not events; mayCreate python: mayEdit and not events;
@ -84,6 +106,8 @@
</tal:others> </tal:others>
</tal:day> </tal:day>
</td> </td>
</tal:td>
</tal:cel>
</tal:cell> </tal:cell>
</tr> </tr>
</table> </table>
@ -157,9 +181,9 @@
<tal:comment replace="nothing">View macro</tal:comment> <tal:comment replace="nothing">View macro</tal:comment>
<metal:view define-macro="view" <metal:view define-macro="view"
tal:define="now python: DateTime(); tal:define="defaultDate python: contextObj.callField(widget['name'], 'getDefaultDate', contextObj);
dummy python: request.set('fieldName', widget['name']); dummy python: request.set('fieldName', widget['name']);
dummy python: request.set('month', now.strftime('%Y/%m'))"> dummy python: request.set('month', defaultDate.strftime('%Y/%m'))">
<metal:call use-macro="app/ui/widgets/calendar/macros/viewMonth"/> <metal:call use-macro="app/ui/widgets/calendar/macros/viewMonth"/>
</metal:view> </metal:view>