From 1f341564378fce570278a3bb33d382f73318c603 Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Thu, 19 Feb 2015 13:40:12 +0100 Subject: [PATCH] [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. --- __init__.py | 6 +++++- fields/calendar.py | 19 ++++++++++++++----- fields/group.py | 2 +- fields/list.py | 17 +++++++++++------ fields/ref.py | 9 ++++----- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/__init__.py b/__init__.py index 91788e0..17489b5 100644 --- a/__init__.py +++ b/__init__.py @@ -40,9 +40,13 @@ class Object: def get(self, name, default=None): return getattr(self, name, default) def __getitem__(self, k): return getattr(self, k) 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(): setattr(self, k, v) + def clone(self): + res = Object() + res.update(self) + return res # ------------------------------------------------------------------------------ class Hack: diff --git a/fields/calendar.py b/fields/calendar.py index 36b323e..03df3cc 100644 --- a/fields/calendar.py +++ b/fields/calendar.py @@ -89,7 +89,7 @@ class Calendar(Field): var2="events=field.getEventsAt(zobj, date); spansDays=field.hasEventsAt(zobj, date+1, events); mayCreate=mayEdit and not events; - mayDelete=mayEdit and events; + mayDelete=mayEdit and events and field.mayDelete(obj,events); day=date.day(); dayString=date.strftime('%Y/%m/%d'); js=mayEdit and 'toggleVisibility(this, %s)' % q('img') \ @@ -216,7 +216,7 @@ class Calendar(Field): mapping=None, label=None, maxEventLength=50, otherCalendars=None, additionalInfo=None, startDate=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, layouts, move, False, True, False, specificReadPermission, 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 # sub-set of the possible event types (or even no event at all). 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): '''Returns the result of calling self.preComputed, or None if no such @@ -573,9 +576,9 @@ class Calendar(Field): eventSpan = rq.get('eventSpan', None) # Split the p_date into separate parts 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): - # 1st level: create a IOBTree whose keys are years. + # 1st level: create a IOBTree whose keys are years setattr(obj, self.name, IOBTree()) yearsDict = getattr(obj, self.name) # Get the sub-dict storing months for a given year @@ -593,7 +596,7 @@ class Calendar(Field): events = daysDict[day] else: 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: event = Object(eventType=eventType) events.append(event) @@ -604,6 +607,12 @@ class Calendar(Field): date = date + 1 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): '''Deletes an event. It actually deletes all events at p_date. If p_handleEventSpan is True, we will use rq["deleteNext"] to diff --git a/fields/group.py b/fields/group.py index 8d71fc6..540f2b2 100644 --- a/fields/group.py +++ b/fields/group.py @@ -179,7 +179,7 @@ class Group: return uiGroup 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"): self.width = width self.align = align diff --git a/fields/list.py b/fields/list.py index 93b9eb5..b709808 100644 --- a/fields/list.py +++ b/fields/list.py @@ -22,9 +22,11 @@ from appy.gen.layout import Table # ------------------------------------------------------------------------------ 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(''' ''') - # PX for rendering the list (shared between pxView and pxEdit). + # PX for rendering the list (shared between pxView and pxEdit) pxTable = Px(''' = len(outerValue): return '' - # Return the value, or a potential default value. - return getattr(outerValue[i], name, '') or \ - self.getField(name).getValue(obj) or '' + # Return the value, or a potential default value + value = getattr(outerValue[i], name, None) + if value != None: return value + value = self.getField(name).getValue(obj) + if value != None: return value + return '' def getCss(self, layoutType, res): '''Gets the CSS required by sub-fields if any.''' diff --git a/fields/ref.py b/fields/ref.py index 3da2014..faf5714 100644 --- a/fields/ref.py +++ b/fields/ref.py @@ -248,6 +248,10 @@ class Ref(Field): q('%s/search?className=%s&ref=%s:%s' % \ (ztool.absolute_url(), tiedClassName, zobj.id, field.name))"/> + :tool.pxNavigate @@ -261,11 +265,6 @@ class Ref(Field): var2="columns=ztool.getColumnsSpecifiers(tiedClassName, \ field.getAttribute(obj, 'shownInfo'), dir); currentNumber=0"> -