diff --git a/fields/calendar.py b/fields/calendar.py index 0f1b293..c4553b6 100644 --- a/fields/calendar.py +++ b/fields/calendar.py @@ -13,9 +13,28 @@ class Calendar(Field): events on it.''' jsFiles = {'view': ('calendar.js',)} DateTime = DateTime + timelineBgColors = {'Fri': '#a6a6a6', 'Sat': '#c0c0c0', 'Sun': '#c0c0c0'} # Timeline view for a calendar - pxViewTimeline = Px('''

Hello timeline

''') + pxViewTimeline = Px(''' + + + + + + + + + + + + + + + +
::mInfo.month
L
:str(date.day()).zfill(2)
''') # Month view for a calendar pxViewMonth = Px(''' @@ -33,7 +52,7 @@ class Calendar(Field): var2="tooEarly=startDate and (date < startDate); tooLate=endDate and not tooEarly and (date > endDate); inRange=not tooEarly and not tooLate; - cssClasses=field.getCellStyle(zobj, date, today)"> + cssClasses=field.getCellClass(zobj, date, render, today)"> @@ -330,37 +349,50 @@ class Calendar(Field): return res def getGrid(self, month, render): - '''Creates a list of lists of DateTime objects representing the calendar - grid to render for a given p_month.''' + '''Creates a list of DateTime objects representing the calendar grid to + render for a given p_month. If p_render is "month", it is a list of + lists (one sub-list for every week; indeed, every week is rendered as + a row). If p_render is "timeline", the result is a linear list of + DateTime instances.''' # Month is a string "YYYY/mm" currentDay = DateTime('%s/01 UTC' % month) currentMonth = currentDay.month() - res = [[]] - dayOneNb = currentDay.dow() or 7 # This way, Sunday is 7 and not 0. + isLinear = render == 'timeline' + if isLinear: res = [] + else: res = [[]] + dayOneNb = currentDay.dow() or 7 # This way, Sunday is 7 and not 0 if dayOneNb != 1: previousDate = DateTime(currentDay) - # If the 1st day of the month is not a Monday, start the row with - # the last days of the previous month. + # If the 1st day of the month is not a Monday, integrate the last + # days of the previous month. for i in range(1, dayOneNb): previousDate = previousDate - 1 - res[0].insert(0, previousDate) + if isLinear: + target = res + else: + target = res[0] + target.insert(0, previousDate) finished = False while not finished: - # Insert currentDay in the grid - if len(res[-1]) == 7: - # Create a new row - res.append([currentDay]) + # Insert currentDay in the result + if isLinear: + res.append(currentDay) else: - res[-1].append(currentDay) - currentDay = currentDay + 1 + if len(res[-1]) == 7: + # Create a new row + res.append([currentDay]) + else: + res[-1].append(currentDay) + currentDay += 1 if currentDay.month() != currentMonth: finished = True # Complete, if needed, the last row with the first days of the next - # month. - if len(res[-1]) != 7: - while len(res[-1]) != 7: - res[-1].append(currentDay) - currentDay = currentDay + 1 + # month. Indeed, we must have a complete week, ending with a Sunday. + if isLinear: target = res + else: target = res[-1] + while target[-1].dow() != 0: + target.append(currentDay) + currentDay += 1 return res def getOtherCalendars(self, obj, preComputed): @@ -649,17 +681,58 @@ class Calendar(Field): elif action == 'deleteEvent': return self.deleteEvent(obj, DateTime(rq['day'])) - def getCellStyle(self, obj, date, today): - '''What CSS classes must apply to the table cell representing p_date + def getCellStyle(self, obj, date, render, today): + '''What style(s) must apply to the table cell representing p_date in the calendar?''' + if render != 'timeline': return '' + # Cells representing specific days must have a specific background color + res = '' + day = date.aDay() + if day in Calendar.timelineBgColors: + res = 'background-color: %s' % Calendar.timelineBgColors[day] + return res + + def getCellClass(self, obj, date, render, today): + '''What CSS class(es) must apply to the table cell representing p_date + in the calendar?''' + if render != 'month': return '' res = [] - # We must distinguish between past and future dates. + # We must distinguish between past and future dates if date < today: res.append('even') else: res.append('odd') - # Week-end days must have a specific style. + # Week-end days must have a specific style if date.aDay() in ('Sat', 'Sun'): res.append('cellDashed') return ' '.join(res) + + def getTimelineMonths(self, grid, obj): + '''Given the p_grid of dates, this method returns the list of + corresponding months.''' + res = [] + for date in grid: + if not res: + # Get the month correspoding to the first day in the grid + m = Object(month=date.aMonth(), colspan=1, year=date.year()) + res.append(m) + else: + # Augment current month' colspan or create a new one + current = res[-1] + if date.aMonth() == current.month: + current.colspan += 1 + else: + m = Object(month=date.aMonth(), colspan=1, year=date.year()) + res.append(m) + # Replace month short names by translated names whose format may vary + # according to colspan (a higher colspan allow us to produce a longer + # month name). + for m in res: + text = '%s %d' % (obj.translate('month_%s' % m.month), m.year) + if m.colspan < 6: + # Short version: a single letter with an acronym + m.month = '%s' % (text, text[0]) + else: + m.month = text + return res # ------------------------------------------------------------------------------ diff --git a/gen/ui/appy.css b/gen/ui/appy.css index adce9a6..dbab9eb 100644 --- a/gen/ui/appy.css +++ b/gen/ui/appy.css @@ -125,6 +125,8 @@ td.search { padding-top: 8px } .grid th { font-style: italic; font-weight: normal; border-bottom: 5px solid #fdfdfd; padding: 3px 5px 0 5px } .grid td { padding: 3px 3px 0 3px } +.timeline { font-size: 90%; color: #555555 } +.timeline td { text-align: center; padding: 2px 2px 0px 2px } .msgTable { margin: 6px 0; width: 100%; font-size: 93% } .msgTable tr { vertical-align: top } .msgTable td, .msgTable th { border: 1px solid grey; color: #555555;