[gen] Calendar field: more work on the timeline rendering.
This commit is contained in:
parent
bf4a781b5a
commit
92daddb0ab
|
@ -13,9 +13,28 @@ class Calendar(Field):
|
||||||
events on it.'''
|
events on it.'''
|
||||||
jsFiles = {'view': ('calendar.js',)}
|
jsFiles = {'view': ('calendar.js',)}
|
||||||
DateTime = DateTime
|
DateTime = DateTime
|
||||||
|
timelineBgColors = {'Fri': '#a6a6a6', 'Sat': '#c0c0c0', 'Sun': '#c0c0c0'}
|
||||||
|
|
||||||
# Timeline view for a calendar
|
# Timeline view for a calendar
|
||||||
pxViewTimeline = Px('''<p>Hello timeline</p>''')
|
pxViewTimeline = Px('''
|
||||||
|
<table cellpadding="0" cellspacing="0" class="list timeline">
|
||||||
|
<!-- Column specifiers -->
|
||||||
|
<colgroup>
|
||||||
|
<!-- Names of calendars -->
|
||||||
|
<col style="width: 140px"></col>
|
||||||
|
<col for="date in grid"
|
||||||
|
style=":field.getCellStyle(zobj, date, render, today)"></col>
|
||||||
|
</colgroup>
|
||||||
|
<!-- Names of months -->
|
||||||
|
<tr><th></th>
|
||||||
|
<th for="mInfo in field.getTimelineMonths(grid, zobj)"
|
||||||
|
colspan=":mInfo.colspan">::mInfo.month</th>
|
||||||
|
</tr>
|
||||||
|
<!-- Days (letters) -->
|
||||||
|
<tr><td></td><td for="date in grid">L</td></tr>
|
||||||
|
<!-- Days (numbers) -->
|
||||||
|
<tr><td></td><td for="date in grid">:str(date.day()).zfill(2)</td></tr>
|
||||||
|
</table>''')
|
||||||
|
|
||||||
# Month view for a calendar
|
# Month view for a calendar
|
||||||
pxViewMonth = Px('''
|
pxViewMonth = Px('''
|
||||||
|
@ -33,7 +52,7 @@ class Calendar(Field):
|
||||||
var2="tooEarly=startDate and (date < startDate);
|
var2="tooEarly=startDate and (date < startDate);
|
||||||
tooLate=endDate and not tooEarly and (date > endDate);
|
tooLate=endDate and not tooEarly and (date > endDate);
|
||||||
inRange=not tooEarly and not tooLate;
|
inRange=not tooEarly and not tooLate;
|
||||||
cssClasses=field.getCellStyle(zobj, date, today)">
|
cssClasses=field.getCellClass(zobj, date, render, today)">
|
||||||
<!-- Dump an empty cell if we are out of the supported date range -->
|
<!-- Dump an empty cell if we are out of the supported date range -->
|
||||||
<td if="not inRange" class=":cssClasses"></td>
|
<td if="not inRange" class=":cssClasses"></td>
|
||||||
<!-- Dump a normal cell if we are in range -->
|
<!-- Dump a normal cell if we are in range -->
|
||||||
|
@ -330,37 +349,50 @@ class Calendar(Field):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getGrid(self, month, render):
|
def getGrid(self, month, render):
|
||||||
'''Creates a list of lists of DateTime objects representing the calendar
|
'''Creates a list of DateTime objects representing the calendar grid to
|
||||||
grid to render for a given p_month.'''
|
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"
|
# Month is a string "YYYY/mm"
|
||||||
currentDay = DateTime('%s/01 UTC' % month)
|
currentDay = DateTime('%s/01 UTC' % month)
|
||||||
currentMonth = currentDay.month()
|
currentMonth = currentDay.month()
|
||||||
res = [[]]
|
isLinear = render == 'timeline'
|
||||||
dayOneNb = currentDay.dow() or 7 # This way, Sunday is 7 and not 0.
|
if isLinear: res = []
|
||||||
|
else: res = [[]]
|
||||||
|
dayOneNb = currentDay.dow() or 7 # This way, Sunday is 7 and not 0
|
||||||
if dayOneNb != 1:
|
if dayOneNb != 1:
|
||||||
previousDate = DateTime(currentDay)
|
previousDate = DateTime(currentDay)
|
||||||
# If the 1st day of the month is not a Monday, start the row with
|
# If the 1st day of the month is not a Monday, integrate the last
|
||||||
# the last days of the previous month.
|
# days of the previous month.
|
||||||
for i in range(1, dayOneNb):
|
for i in range(1, dayOneNb):
|
||||||
previousDate = previousDate - 1
|
previousDate = previousDate - 1
|
||||||
res[0].insert(0, previousDate)
|
if isLinear:
|
||||||
|
target = res
|
||||||
|
else:
|
||||||
|
target = res[0]
|
||||||
|
target.insert(0, previousDate)
|
||||||
finished = False
|
finished = False
|
||||||
while not finished:
|
while not finished:
|
||||||
# Insert currentDay in the grid
|
# Insert currentDay in the result
|
||||||
|
if isLinear:
|
||||||
|
res.append(currentDay)
|
||||||
|
else:
|
||||||
if len(res[-1]) == 7:
|
if len(res[-1]) == 7:
|
||||||
# Create a new row
|
# Create a new row
|
||||||
res.append([currentDay])
|
res.append([currentDay])
|
||||||
else:
|
else:
|
||||||
res[-1].append(currentDay)
|
res[-1].append(currentDay)
|
||||||
currentDay = currentDay + 1
|
currentDay += 1
|
||||||
if currentDay.month() != currentMonth:
|
if currentDay.month() != currentMonth:
|
||||||
finished = True
|
finished = True
|
||||||
# Complete, if needed, the last row with the first days of the next
|
# Complete, if needed, the last row with the first days of the next
|
||||||
# month.
|
# month. Indeed, we must have a complete week, ending with a Sunday.
|
||||||
if len(res[-1]) != 7:
|
if isLinear: target = res
|
||||||
while len(res[-1]) != 7:
|
else: target = res[-1]
|
||||||
res[-1].append(currentDay)
|
while target[-1].dow() != 0:
|
||||||
currentDay = currentDay + 1
|
target.append(currentDay)
|
||||||
|
currentDay += 1
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getOtherCalendars(self, obj, preComputed):
|
def getOtherCalendars(self, obj, preComputed):
|
||||||
|
@ -649,17 +681,58 @@ class Calendar(Field):
|
||||||
elif action == 'deleteEvent':
|
elif action == 'deleteEvent':
|
||||||
return self.deleteEvent(obj, DateTime(rq['day']))
|
return self.deleteEvent(obj, DateTime(rq['day']))
|
||||||
|
|
||||||
def getCellStyle(self, obj, date, today):
|
def getCellStyle(self, obj, date, render, today):
|
||||||
'''What CSS classes must apply to the table cell representing p_date
|
'''What style(s) must apply to the table cell representing p_date
|
||||||
in the calendar?'''
|
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 = []
|
res = []
|
||||||
# We must distinguish between past and future dates.
|
# We must distinguish between past and future dates
|
||||||
if date < today:
|
if date < today:
|
||||||
res.append('even')
|
res.append('even')
|
||||||
else:
|
else:
|
||||||
res.append('odd')
|
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'):
|
if date.aDay() in ('Sat', 'Sun'):
|
||||||
res.append('cellDashed')
|
res.append('cellDashed')
|
||||||
return ' '.join(res)
|
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 = '<acronym title="%s">%s</acronym>' % (text, text[0])
|
||||||
|
else:
|
||||||
|
m.month = text
|
||||||
|
return res
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -125,6 +125,8 @@ td.search { padding-top: 8px }
|
||||||
.grid th { font-style: italic; font-weight: normal;
|
.grid th { font-style: italic; font-weight: normal;
|
||||||
border-bottom: 5px solid #fdfdfd; padding: 3px 5px 0 5px }
|
border-bottom: 5px solid #fdfdfd; padding: 3px 5px 0 5px }
|
||||||
.grid td { padding: 3px 3px 0 3px }
|
.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 { margin: 6px 0; width: 100%; font-size: 93% }
|
||||||
.msgTable tr { vertical-align: top }
|
.msgTable tr { vertical-align: top }
|
||||||
.msgTable td, .msgTable th { border: 1px solid grey; color: #555555;
|
.msgTable td, .msgTable th { border: 1px solid grey; color: #555555;
|
||||||
|
|
Loading…
Reference in a new issue