[gen] List field: bugfix with empty-like values (integer 0 for example). Ref field: bugfix: add a tied object with noForm=True. Calendar: added param 'delete' allowing to define who can delete what event type in the calendar. Added method 'clone' on class appy.Object.
This commit is contained in:
parent
5ba648fbf0
commit
1f34156437
|
@ -40,9 +40,13 @@ class Object:
|
||||||
def get(self, name, default=None): return getattr(self, name, default)
|
def get(self, name, default=None): return getattr(self, name, default)
|
||||||
def __getitem__(self, k): return getattr(self, k)
|
def __getitem__(self, k): return getattr(self, k)
|
||||||
def update(self, other):
|
def update(self, other):
|
||||||
'''Includes information from p_other into p_self.'''
|
'''Includes information from p_other into p_self'''
|
||||||
for k, v in other.__dict__.iteritems():
|
for k, v in other.__dict__.iteritems():
|
||||||
setattr(self, k, v)
|
setattr(self, k, v)
|
||||||
|
def clone(self):
|
||||||
|
res = Object()
|
||||||
|
res.update(self)
|
||||||
|
return res
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Hack:
|
class Hack:
|
||||||
|
|
|
@ -89,7 +89,7 @@ class Calendar(Field):
|
||||||
var2="events=field.getEventsAt(zobj, date);
|
var2="events=field.getEventsAt(zobj, date);
|
||||||
spansDays=field.hasEventsAt(zobj, date+1, events);
|
spansDays=field.hasEventsAt(zobj, date+1, events);
|
||||||
mayCreate=mayEdit and not events;
|
mayCreate=mayEdit and not events;
|
||||||
mayDelete=mayEdit and events;
|
mayDelete=mayEdit and events and field.mayDelete(obj,events);
|
||||||
day=date.day();
|
day=date.day();
|
||||||
dayString=date.strftime('%Y/%m/%d');
|
dayString=date.strftime('%Y/%m/%d');
|
||||||
js=mayEdit and 'toggleVisibility(this, %s)' % q('img') \
|
js=mayEdit and 'toggleVisibility(this, %s)' % q('img') \
|
||||||
|
@ -216,7 +216,7 @@ class Calendar(Field):
|
||||||
mapping=None, label=None, maxEventLength=50,
|
mapping=None, label=None, maxEventLength=50,
|
||||||
otherCalendars=None, additionalInfo=None, startDate=None,
|
otherCalendars=None, additionalInfo=None, startDate=None,
|
||||||
endDate=None, defaultDate=None, preCompute=None,
|
endDate=None, defaultDate=None, preCompute=None,
|
||||||
applicableEvents=None, view=None, xml=None):
|
applicableEvents=None, view=None, xml=None, delete=True):
|
||||||
Field.__init__(self, validator, (0,1), default, show, page, group,
|
Field.__init__(self, validator, (0,1), default, show, page, group,
|
||||||
layouts, move, False, True, False, specificReadPermission,
|
layouts, move, False, True, False, specificReadPermission,
|
||||||
specificWritePermission, width, height, None, colspan,
|
specificWritePermission, width, height, None, colspan,
|
||||||
|
@ -294,6 +294,9 @@ class Calendar(Field):
|
||||||
# for explaining him why he can, for this day, only create events of a
|
# for explaining him why he can, for this day, only create events of a
|
||||||
# sub-set of the possible event types (or even no event at all).
|
# sub-set of the possible event types (or even no event at all).
|
||||||
self.applicableEvents = applicableEvents
|
self.applicableEvents = applicableEvents
|
||||||
|
# May the user delete events in this calendar? If "delete" is a method,
|
||||||
|
# it must accept an event type as single arg.
|
||||||
|
self.delete = delete
|
||||||
|
|
||||||
def getPreComputedInfo(self, obj, monthDayOne, grid):
|
def getPreComputedInfo(self, obj, monthDayOne, grid):
|
||||||
'''Returns the result of calling self.preComputed, or None if no such
|
'''Returns the result of calling self.preComputed, or None if no such
|
||||||
|
@ -573,9 +576,9 @@ class Calendar(Field):
|
||||||
eventSpan = rq.get('eventSpan', None)
|
eventSpan = rq.get('eventSpan', None)
|
||||||
# Split the p_date into separate parts
|
# Split the p_date into separate parts
|
||||||
year, month, day = date.year(), date.month(), date.day()
|
year, month, day = date.year(), date.month(), date.day()
|
||||||
# Check that the "preferences" dict exists or not.
|
# Check that the "preferences" dict exists or not
|
||||||
if not hasattr(obj.aq_base, self.name):
|
if not hasattr(obj.aq_base, self.name):
|
||||||
# 1st level: create a IOBTree whose keys are years.
|
# 1st level: create a IOBTree whose keys are years
|
||||||
setattr(obj, self.name, IOBTree())
|
setattr(obj, self.name, IOBTree())
|
||||||
yearsDict = getattr(obj, self.name)
|
yearsDict = getattr(obj, self.name)
|
||||||
# Get the sub-dict storing months for a given year
|
# Get the sub-dict storing months for a given year
|
||||||
|
@ -593,7 +596,7 @@ class Calendar(Field):
|
||||||
events = daysDict[day]
|
events = daysDict[day]
|
||||||
else:
|
else:
|
||||||
daysDict[day] = events = PersistentList()
|
daysDict[day] = events = PersistentList()
|
||||||
# Create and store the event, excepted if an event already exists.
|
# Create and store the event, excepted if an event already exists
|
||||||
if not events:
|
if not events:
|
||||||
event = Object(eventType=eventType)
|
event = Object(eventType=eventType)
|
||||||
events.append(event)
|
events.append(event)
|
||||||
|
@ -604,6 +607,12 @@ class Calendar(Field):
|
||||||
date = date + 1
|
date = date + 1
|
||||||
self.createEvent(obj, date, handleEventSpan=False)
|
self.createEvent(obj, date, handleEventSpan=False)
|
||||||
|
|
||||||
|
def mayDelete(self, obj, events):
|
||||||
|
'''May the user delete p_events?'''
|
||||||
|
if not self.delete: return
|
||||||
|
if callable(self.delete): return self.delete(obj, events[0].eventType)
|
||||||
|
return True
|
||||||
|
|
||||||
def deleteEvent(self, obj, date, handleEventSpan=True):
|
def deleteEvent(self, obj, date, handleEventSpan=True):
|
||||||
'''Deletes an event. It actually deletes all events at p_date.
|
'''Deletes an event. It actually deletes all events at p_date.
|
||||||
If p_handleEventSpan is True, we will use rq["deleteNext"] to
|
If p_handleEventSpan is True, we will use rq["deleteNext"] to
|
||||||
|
|
|
@ -179,7 +179,7 @@ class Group:
|
||||||
return uiGroup
|
return uiGroup
|
||||||
|
|
||||||
class Column:
|
class Column:
|
||||||
'''Used for describing a column within a Group like defined above.'''
|
'''Used for describing a column within a Group like defined above'''
|
||||||
def __init__(self, width, align="left"):
|
def __init__(self, width, align="left"):
|
||||||
self.width = width
|
self.width = width
|
||||||
self.align = align
|
self.align = align
|
||||||
|
|
|
@ -22,9 +22,11 @@ from appy.gen.layout import Table
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class List(Field):
|
class List(Field):
|
||||||
'''A list.'''
|
'''A list, stored as a list of Object instances ~[Object]~. Every object in
|
||||||
|
the list has attributes named according to the sub-fields defined in this
|
||||||
|
List.'''
|
||||||
|
|
||||||
# PX for rendering a single row.
|
# PX for rendering a single row
|
||||||
pxRow = Px('''
|
pxRow = Px('''
|
||||||
<tr valign="top" style=":(rowIndex==-1) and 'display: none' or ''">
|
<tr valign="top" style=":(rowIndex==-1) and 'display: none' or ''">
|
||||||
<td for="info in subFields" if="info[1]" align="center"
|
<td for="info in subFields" if="info[1]" align="center"
|
||||||
|
@ -38,7 +40,7 @@ class List(Field):
|
||||||
</td>
|
</td>
|
||||||
</tr>''')
|
</tr>''')
|
||||||
|
|
||||||
# PX for rendering the list (shared between pxView and pxEdit).
|
# PX for rendering the list (shared between pxView and pxEdit)
|
||||||
pxTable = Px('''
|
pxTable = Px('''
|
||||||
<table var="isEdit=layoutType == 'edit'" if="isEdit or value"
|
<table var="isEdit=layoutType == 'edit'" if="isEdit or value"
|
||||||
id=":'list_%s' % name" class=":isEdit and 'grid' or 'list'"
|
id=":'list_%s' % name" class=":isEdit and 'grid' or 'list'"
|
||||||
|
@ -177,9 +179,12 @@ class List(Field):
|
||||||
if i == -1: return ''
|
if i == -1: return ''
|
||||||
if not outerValue: return ''
|
if not outerValue: return ''
|
||||||
if i >= len(outerValue): return ''
|
if i >= len(outerValue): return ''
|
||||||
# Return the value, or a potential default value.
|
# Return the value, or a potential default value
|
||||||
return getattr(outerValue[i], name, '') or \
|
value = getattr(outerValue[i], name, None)
|
||||||
self.getField(name).getValue(obj) or ''
|
if value != None: return value
|
||||||
|
value = self.getField(name).getValue(obj)
|
||||||
|
if value != None: return value
|
||||||
|
return ''
|
||||||
|
|
||||||
def getCss(self, layoutType, res):
|
def getCss(self, layoutType, res):
|
||||||
'''Gets the CSS required by sub-fields if any.'''
|
'''Gets the CSS required by sub-fields if any.'''
|
||||||
|
|
|
@ -248,6 +248,10 @@ class Ref(Field):
|
||||||
q('%s/search?className=%s&ref=%s:%s' % \
|
q('%s/search?className=%s&ref=%s:%s' % \
|
||||||
(ztool.absolute_url(), tiedClassName, zobj.id, field.name))"/>
|
(ztool.absolute_url(), tiedClassName, zobj.id, field.name))"/>
|
||||||
</div>
|
</div>
|
||||||
|
<script>:field.getAjaxData(ajaxHookId, zobj, popup=inPopup, \
|
||||||
|
checkboxes=checkboxes, startNumber=startNumber, sourceId=zobj.id, \
|
||||||
|
totalNumber=totalNumber, refFieldName=field.name, \
|
||||||
|
inPickList=inPickList, numbered=numbered)</script>
|
||||||
|
|
||||||
<!-- (Top) navigation -->
|
<!-- (Top) navigation -->
|
||||||
<x>:tool.pxNavigate</x>
|
<x>:tool.pxNavigate</x>
|
||||||
|
@ -261,11 +265,6 @@ class Ref(Field):
|
||||||
var2="columns=ztool.getColumnsSpecifiers(tiedClassName, \
|
var2="columns=ztool.getColumnsSpecifiers(tiedClassName, \
|
||||||
field.getAttribute(obj, 'shownInfo'), dir);
|
field.getAttribute(obj, 'shownInfo'), dir);
|
||||||
currentNumber=0">
|
currentNumber=0">
|
||||||
<script>:field.getAjaxData(ajaxHookId, zobj, popup=inPopup, \
|
|
||||||
checkboxes=checkboxes, startNumber=startNumber, \
|
|
||||||
totalNumber=totalNumber, sourceId=zobj.id, \
|
|
||||||
refFieldName=field.name, inPickList=inPickList, \
|
|
||||||
numbered=numbered)</script>
|
|
||||||
|
|
||||||
<tr if="field.showHeaders">
|
<tr if="field.showHeaders">
|
||||||
<th if="not inPickList and numbered" width=":numbered"></th>
|
<th if="not inPickList and numbered" width=":numbered"></th>
|
||||||
|
|
Loading…
Reference in a new issue