[gen] Continued PX-based refactoring.
This commit is contained in:
parent
25b4edfc1d
commit
369e41b43c
|
@ -356,7 +356,7 @@ class Field:
|
|||
# represents the maximum number of chars that a given input field may
|
||||
# accept (corresponds to HTML "maxlength" property). "None" means
|
||||
# "unlimited".
|
||||
self.maxChars = maxChars
|
||||
self.maxChars = maxChars or ''
|
||||
# If the widget is in a group with multiple columns, the following
|
||||
# attribute specifies on how many columns to span the widget.
|
||||
self.colspan = colspan
|
||||
|
|
|
@ -28,20 +28,20 @@ class Action(Field):
|
|||
pxView = pxCell = Px('''
|
||||
<form name="executeAppyAction"
|
||||
var="formId='%s_%s_form' % (contextObj.UID(), name);
|
||||
label=_(widget['labelId'])"
|
||||
label=_(field.labelId)"
|
||||
id=":formId" action=":ztool.absolute_url() + '/do'">
|
||||
<input type="hidden" name="action" value="ExecuteAppyAction"/>
|
||||
<input type="hidden" name="objectUid" value=":contextObj.UID()"/>
|
||||
<input type="hidden" name="fieldName" value=":name"/>
|
||||
<x if="widget['confirm']"><input
|
||||
<x if="field.confirm"><input
|
||||
type="button" class="button"
|
||||
var="labelConfirm=_(widget['labelId'] + '_confirm')"
|
||||
var="labelConfirm=_(field.labelId + '_confirm')"
|
||||
value=":ztool.truncateValue(label)" title=":label"
|
||||
style=":'background-image: url(%s/ui/buttonAction.png)' % appUrl"
|
||||
onclick=":'askConfirm(%s,%s,%s)' % (q('form'), q(formId), \
|
||||
q(labelConfirm))"/>
|
||||
</x>
|
||||
<input if="not widget['confirm']" type="submit" class="button" name="do"
|
||||
<input if="not field.confirm" type="submit" class="button" name="do"
|
||||
value=":ztool.truncateValue(label)" title=":label"
|
||||
style=":'background-image: url(%s/ui/buttonAction.png)' % appUrl"/>
|
||||
</form>''')
|
||||
|
|
|
@ -30,7 +30,7 @@ class Boolean(Field):
|
|||
</x>''')
|
||||
|
||||
pxEdit = Px('''
|
||||
<x var="isChecked=contextObj.checkboxChecked(name, rawValue)">
|
||||
<x var="isChecked=field.isChecked(contextObj, rawValue)">
|
||||
<input type="checkbox" name=":name + '_visible'" id=":name"
|
||||
class=":masterCss" checked=":isChecked"
|
||||
onclick=":'toggleCheckbox(%s, %s); updateSlaves(this)' % \
|
||||
|
@ -41,10 +41,10 @@ class Boolean(Field):
|
|||
|
||||
pxSearch = Px('''
|
||||
<x var="typedWidget='%s*bool' % widgetName">
|
||||
<label lfor=":widgetName">:_(widget['labelId'])"></label><br/>
|
||||
<label lfor=":widgetName">:_(field.labelId)"></label><br/>
|
||||
<x var="valueId='%s_yes' % name">
|
||||
<input type="radio" value="True" name=":typedWidget" id=":valueId"/>
|
||||
<label lfor=":valueId">:_('yes')"></label>
|
||||
<label lfor=":valueId">:_('yes')</label>
|
||||
</x>
|
||||
<x var="valueId='%s_no' % name">
|
||||
<input type="radio" value="False" name=":typedWidget" id=":valueId"/>
|
||||
|
@ -53,7 +53,7 @@ class Boolean(Field):
|
|||
<x var="valueId='%s_whatever' % name">
|
||||
<input type="radio" value="" name=":typedWidget" id=":valueId"
|
||||
checked="checked"/>
|
||||
<label lfor=":valueId">:_('whatever')"></label>
|
||||
<label lfor=":valueId">:_('whatever')</label>
|
||||
</x><br/>
|
||||
</x>''')
|
||||
|
||||
|
@ -96,4 +96,13 @@ class Boolean(Field):
|
|||
if not self.isEmptyValue(value):
|
||||
exec 'res = %s' % value
|
||||
return res
|
||||
|
||||
def isChecked(self, obj, dbValue):
|
||||
'''When rendering this field as a checkbox, must it be checked or
|
||||
not?'''
|
||||
rq = obj.REQUEST
|
||||
# Get the value we must compare (from request or from database)
|
||||
if rq.has_key(self.name):
|
||||
return rq.get(self.name) in ('True', 1, '1')
|
||||
return dbValue
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -16,35 +16,28 @@ class Calendar(Field):
|
|||
# Month view for a calendar. Called by pxView, and directly from the UI,
|
||||
# via Ajax, when the user selects another month.
|
||||
pxMonthView = Px('''
|
||||
<div var="fieldName=req['fieldName'];
|
||||
ajaxHookId=contextObj.UID() + fieldName;
|
||||
<div var="field=contextObj.getAppyType(req['fieldName']);
|
||||
ajaxHookId=contextObj.UID() + field.name;
|
||||
month=req['month'];
|
||||
monthDayOne=DateTime('%s/01' % month);
|
||||
today=DateTime('00:00');
|
||||
grid=contextObj.callField(fieldName, 'getMonthGrid', month);
|
||||
allEventTypes=contextObj.callField(fieldName, 'getEventTypes', \
|
||||
contextObj);
|
||||
preComputed=contextObj.callField(fieldName, \
|
||||
'getPreComputedInfo', contextObj, monthDayOne, grid);
|
||||
defaultDate=contextObj.callField(fieldName, 'getDefaultDate', \
|
||||
contextObj);
|
||||
grid=field.getMonthGrid(month);
|
||||
allEventTypes=field.getEventTypes(contextObj);
|
||||
preComputed=field.getPreComputedInfo(contextObj, monthDayOne, \
|
||||
grid);
|
||||
defaultDate=field.getDefaultDate(contextObj);
|
||||
defaultDateMonth=defaultDate.strftime('%Y/%m');
|
||||
previousMonth=contextObj.callField(fieldName, \
|
||||
'getSiblingMonth', month, 'previous');
|
||||
nextMonth=contextObj.callField(fieldName, 'getSiblingMonth', \
|
||||
month, 'next');
|
||||
widget=contextObj.getAppyType(fieldName, asDict=True);
|
||||
previousMonth=field.getSiblingMonth(month, 'previous');
|
||||
nextMonth=field.getSiblingMonth(month, 'next');
|
||||
mayEdit=contextObj.allows(widget['writePermission']);
|
||||
objUrl=contextObj/absolute_url();
|
||||
startDate=contextObj.callField(fieldName, 'getStartDate', \
|
||||
contextObj);
|
||||
endDate=contextObj.callField(fieldName, 'getEndDate',contextObj);
|
||||
otherCalendars=contextObj.callField(fieldName, \
|
||||
'getOtherCalendars', contextObj, preComputed)"
|
||||
objUrl=contextObj.absolute_url();
|
||||
startDate=field.getStartDate(contextObj);
|
||||
endDate=field.getEndDate(contextObj);
|
||||
otherCalendars=field.getOtherCalendars(contextObj, preComputed)"
|
||||
id=":ajaxHookId">
|
||||
|
||||
<script type="text/javascript">:'var %s_maxEventLength = %d;' % \
|
||||
(fieldName, widget['maxEventLength'])">
|
||||
(field.name, field.maxEventLength)">
|
||||
</script>
|
||||
|
||||
<!-- Month chooser -->
|
||||
|
@ -58,7 +51,7 @@ class Calendar(Field):
|
|||
<img style="cursor:pointer" tal:condition="goBack"
|
||||
src=":'%s/ui/arrowLeftSimple.png' % appUrl"
|
||||
onclick=":'askMonthView(%s, %s, %s, %s)' % \
|
||||
(q(ajaxHookId),q(objUrl),q(fieldName),q(previousMonth))"/>
|
||||
(q(ajaxHookId),q(objUrl),q(field.name),q(previousMonth))"/>
|
||||
<!-- Go back to the default date -->
|
||||
<x if="goBack or goForward">
|
||||
<input type="button"
|
||||
|
@ -67,14 +60,14 @@ class Calendar(Field):
|
|||
'today' or 'goto_source'"
|
||||
value=":_(label)"
|
||||
onclick=":'askMonthView(%s, %s, %s, %s)' % (q(ajaxHookId), \
|
||||
q(objUrl), q(fieldName), q(defaultDateMonth))"
|
||||
q(objUrl), q(field.name), q(defaultDateMonth))"
|
||||
disabled=":defaultDate.strftime(fmt)==monthDayOne.strftime(fmt)"/>
|
||||
</x>
|
||||
<!-- Go to the next month -->
|
||||
<img style="cursor:pointer" if="goForward"
|
||||
src=":'%s/ui/arrowRightSimple.png' % appUrl"
|
||||
onclick=":'askMonthView(%s, %s, %s, %s)' % (q(ajaxHookId), \
|
||||
q(objUrl), q(fieldName), q(nextMonth))"/>
|
||||
q(objUrl), q(field.name), q(nextMonth))"/>
|
||||
<span>:_('month_%s' % monthDayOne.aMonth())</span>
|
||||
<span>:month.split('/')[0]</span>
|
||||
</div>
|
||||
|
@ -82,11 +75,10 @@ class Calendar(Field):
|
|||
<!-- Calendar month view -->
|
||||
<table cellpadding="0" cellspacing="0" width="100%" class="list"
|
||||
style="font-size: 95%"
|
||||
var="rowHeight=int(widget['height']/float(len(grid)))">
|
||||
var="rowHeight=int(field.height/float(len(grid)))">
|
||||
<!-- 1st row: names of days -->
|
||||
<tr height="22px">
|
||||
<th for="dayName in contextObj.callField(fieldName, 'getNamesOfDays', \
|
||||
contextObj)"
|
||||
<th for="dayName in field.getNamesOfDays(contextObj)"
|
||||
width="14%">:dayName</th>
|
||||
</tr>
|
||||
<!-- The calendar in itself -->
|
||||
|
@ -95,16 +87,13 @@ class Calendar(Field):
|
|||
<x var="tooEarly=startDate and (date < startDate);
|
||||
tooLate=endDate and not tooEarly and (date > endDate);
|
||||
inRange=not tooEarly and not tooLate;
|
||||
cssClasses=contextObj.callField(fieldName, 'getCellStyle', \
|
||||
contextObj, date, today)">
|
||||
cssClasses=field.getCellStyle(contextObj, date, today)">
|
||||
<!-- Dump an empty cell if we are out of the supported date range -->
|
||||
<td if="not inRange" class=":cssClasses"></td>
|
||||
<!-- Dump a normal cell if we are in range -->
|
||||
<x if="inRange">
|
||||
<td var="events=contextObj.callField(fieldName, 'getEventsAt', \
|
||||
contextObj, date);
|
||||
spansDays=contextObj.callField(fieldName, 'hasEventsAt', \
|
||||
contextObj, date+1, events);
|
||||
<td var="events=field.getEventsAt(contextObj, date);
|
||||
spansDays=field.hasEventsAt(contextObj, date+1, events);
|
||||
mayCreate=mayEdit and not events;
|
||||
mayDelete=mayEdit and events"
|
||||
style="date.isCurrentDay() and 'font-weight:bold' or \
|
||||
|
@ -121,39 +110,37 @@ class Calendar(Field):
|
|||
<!-- Icon for adding an event -->
|
||||
<x if="mayCreate">
|
||||
<img style="visibility:hidden; cursor:pointer"
|
||||
var="info=contextObj.callField(fieldName, \
|
||||
'getApplicableEventsTypesAt', contextObj, date, \
|
||||
var="info=field.getApplicableEventsTypesAt(contextObj, date, \
|
||||
allEventTypes, preComputed, True)"
|
||||
if="info['eventTypes']"
|
||||
src=":'%s/ui/plus.png' % appUrl"
|
||||
onclick=":'openEventPopup(%s, %s, %s, null, %s, %s)' % \
|
||||
(q('new'), q(fieldName), q(dayString), \
|
||||
(q('new'), q(field.name), q(dayString), \
|
||||
q(info['eventTypes']), q(info['message']))"/>
|
||||
</x>
|
||||
<!-- Icon for deleting an event -->
|
||||
<img if="mayDelete" style="visibility:hidden; cursor:pointer"
|
||||
src=":'%s/ui/delete.png' % appUrl"
|
||||
onclick=":'openEventPopup(%s, %s, %s, %s, null, null)' % \
|
||||
(q('del'), q(fieldName), q(dayString), q(str(spansDays)))"/>
|
||||
(q('del'), q(field.name), q(dayString), q(str(spansDays)))"/>
|
||||
<x if="events">
|
||||
<!-- A single event is allowed for the moment -->
|
||||
<div var="eventType=events[0]['eventType']">
|
||||
<span style="color: grey">:contextObj.callField(fieldName, \
|
||||
'getEventName', contextObj, eventType)"></span>
|
||||
<span style="color: grey">:field.getEventName(contextObj, \
|
||||
eventType)"></span>
|
||||
</div>
|
||||
</x>
|
||||
<!-- Events from other calendars -->
|
||||
<x if="otherCalendars">
|
||||
<x var="otherEvents=contextObj.callField(fieldName, \
|
||||
'getOtherEventsAt', contextObj, date, otherCalendars)"
|
||||
<x var="otherEvents=field.getOtherEventsAt(contextObj, date, \
|
||||
otherCalendars)"
|
||||
if="otherEvents">
|
||||
<div style=":'color: %s; font-style: italic' % event['color']"
|
||||
for="event in otherEvents">:event['name']</div>
|
||||
</x>
|
||||
</x>
|
||||
<!-- Additional info -->
|
||||
<x var="info=contextObj.callField(fieldName, \
|
||||
'getAdditionalInfoAt', contextObj, date, preComputed)"
|
||||
<x var="info=field.getAdditionalInfoAt(contextObj,date,preComputed)"
|
||||
if="info">::info</x>
|
||||
</x>
|
||||
</td>
|
||||
|
@ -164,13 +151,13 @@ class Calendar(Field):
|
|||
</table>
|
||||
|
||||
<!-- Popup for creating a calendar event -->
|
||||
<div var="prefix='%s_newEvent' % fieldName;
|
||||
<div var="prefix='%s_newEvent' % field.name;
|
||||
popupId=prefix + 'Popup'"
|
||||
id=":popupId" class="popup" align="center">
|
||||
<form id="prefix + 'Form'" method="post">
|
||||
<input type="hidden" name="fieldName" value=":fieldName"/>
|
||||
<input type="hidden" name="fieldName" value=":field.name"/>
|
||||
<input type="hidden" name="month" value=":month"/>
|
||||
<input type="hidden" name="name" value=":fieldName"/>
|
||||
<input type="hidden" name="name" value=":field.name"/>
|
||||
<input type="hidden" name="action" value="Process"/>
|
||||
<input type="hidden" name="actionType" value="createEvent"/>
|
||||
<input type="hidden" name="day"/>
|
||||
|
@ -180,8 +167,7 @@ class Calendar(Field):
|
|||
<select name="eventType">
|
||||
<option value="">:_('choose_a_value')"></option>
|
||||
<option for="eventType in allEventTypes"
|
||||
value=":eventType">:contextObj.callField(fieldName, \
|
||||
'getEventName', contextObj, eventType)">
|
||||
value=":eventType">:field.getEventName(contextObj, eventType)">
|
||||
</option>
|
||||
</select><br/><br/>
|
||||
<!--Span the event on several days -->
|
||||
|
@ -193,7 +179,7 @@ class Calendar(Field):
|
|||
value=":_('object_save')"
|
||||
onclick=":'triggerCalendarEvent(%s, %s, %s, %s, \
|
||||
%s_maxEventLength)' % (q('new'), q(ajaxHookId), \
|
||||
q(fieldName), q(objUrl), fieldName)"/>
|
||||
q(field.name), q(objUrl), field.name)"/>
|
||||
<input type="button"
|
||||
value=":_('object_cancel')"
|
||||
onclick=":'closePopup(%s)' % q(popupId)"/>
|
||||
|
@ -201,13 +187,13 @@ class Calendar(Field):
|
|||
</div>
|
||||
|
||||
<!-- Popup for deleting a calendar event -->
|
||||
<div var="prefix='%s_delEvent' % fieldName;
|
||||
<div var="prefix='%s_delEvent' % field.name;
|
||||
popupId=prefix + 'Popup'"
|
||||
id=":popupId" class="popup" align="center">
|
||||
<form id=":prefix + 'Form'" method="post">
|
||||
<input type="hidden" name="fieldName" value=":fieldName"/>
|
||||
<input type="hidden" name="fieldName" value=":field.name"/>
|
||||
<input type="hidden" name="month" value=":month"/>
|
||||
<input type="hidden" name="name" value=":fieldName"/>
|
||||
<input type="hidden" name="name" value=":field.name"/>
|
||||
<input type="hidden" name="action" value="Process"/>
|
||||
<input type="hidden" name="actionType" value="deleteEvent"/>
|
||||
<input type="hidden" name="day"/>
|
||||
|
@ -227,7 +213,7 @@ class Calendar(Field):
|
|||
</div>
|
||||
<input type="button" value=":_('yes')"
|
||||
onClick=":'triggerCalendarEvent(%s, %s, %s, %s)' % \
|
||||
(q('del'), q(ajaxHookId), q(fieldName), q(objUrl))"/>
|
||||
(q('del'), q(ajaxHookId), q(field.name), q(objUrl))"/>
|
||||
<input type="button" value=":_('no')"
|
||||
onclick=":'closePopup(%s)' % q(popupId)"/>
|
||||
</form>
|
||||
|
@ -235,13 +221,11 @@ class Calendar(Field):
|
|||
</div>''')
|
||||
|
||||
pxView = pxCell = Px('''
|
||||
<x var="defaultDate=contextObj.callField(widget['name'], 'getDefaultDate',\
|
||||
contextObj);
|
||||
x=req.set('fieldName', widget['name']);
|
||||
<x var="defaultDate=field.getDefaultDate(contextObj);
|
||||
x=req.set('fieldName', field.name);
|
||||
x=req.set('month', defaultDate.strftime('%Y/%m'))">
|
||||
<x>:widget['pxMonthView']></x>
|
||||
</x>
|
||||
''')
|
||||
<x>:field.pxMonthView</x>
|
||||
</x>''')
|
||||
|
||||
pxEdit = pxSearch = ''
|
||||
|
||||
|
|
|
@ -24,15 +24,15 @@ class Computed(Field):
|
|||
# Ajax-called view content of a non sync Computed field.
|
||||
pxViewContent = Px('''
|
||||
<x var="name=req['fieldName'];
|
||||
widget=contextObj.getAppyType(name, asDict=True);
|
||||
field=contextObj.getAppyType(name);
|
||||
value=contextObj.getFieldValue(name);
|
||||
sync=True">:widget['pxView']</x>''')
|
||||
sync=True">:field.pxView</x>''')
|
||||
|
||||
pxView = pxCell = pxEdit = Px('''
|
||||
<x>
|
||||
<x if="sync">
|
||||
<x if="widget['plainText']">:value</x>
|
||||
<x if="not widget['plainText']">::value></x>
|
||||
<x if="field.plainText">:value</x>
|
||||
<x if="not field.plainText">::value></x>
|
||||
</x>
|
||||
<x if="not sync">
|
||||
<div var="ajaxHookId=contextObj.UID() + name" id="ajaxHookId">
|
||||
|
@ -45,12 +45,9 @@ class Computed(Field):
|
|||
|
||||
pxSearch = Px('''
|
||||
<x>
|
||||
<label lfor=":widgetName">:_(widget['labelId'])"></label><br/>
|
||||
<input type="text"
|
||||
var="maxChars=widget['maxChars'] and widget['maxChars'] or ''"
|
||||
name=":'%s*string' % widgetName"
|
||||
maxlength=":maxChars" size=":widget['width']"
|
||||
value=":widget['sdefault']"/>
|
||||
<label lfor=":name">:field.labelId</label><br/>
|
||||
<input type="text" name=":'%s*string' % name" maxlength=":field.maxChars"
|
||||
size=":field.width" value=":field.sdefault"/>
|
||||
</x>''')
|
||||
|
||||
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
||||
|
|
|
@ -24,15 +24,15 @@ class Date(Field):
|
|||
|
||||
pxView = pxCell = Px('''<x>:value</x>''')
|
||||
pxEdit = Px('''
|
||||
<x var="years=contextObj.getSelectableYears(widget['name'])">
|
||||
<x var="years=field.getSelectableYears()">
|
||||
<!-- Day -->
|
||||
<select var="days=range(1,32)"
|
||||
name=":'%s_day' % name" id=":'%s_day' % name">
|
||||
<option value="">-</option>
|
||||
<x for="day in days">
|
||||
<option var="zDay=str(day).zfill(2)" value=":zDay"
|
||||
selected="contextObj.dateValueSelected(name, 'day', day, \
|
||||
rawValue)">:zDay></option></x>
|
||||
selected="field.isSelected(contextObj, 'day', day, \
|
||||
rawValue)">:zDay</option></x>
|
||||
</select>
|
||||
|
||||
<!-- Month -->
|
||||
|
@ -41,7 +41,7 @@ class Date(Field):
|
|||
<option value="">-</option>
|
||||
<x for="month in months">
|
||||
<option var="zMonth=str(month).zfill(2)" value=":zMonth"
|
||||
selected="contextObj.dateValueSelected(name, 'month', month, \
|
||||
selected="field.isSelected(contextObj, 'month', month, \
|
||||
rawValue)">:zMonth</option></x>
|
||||
</select>
|
||||
|
||||
|
@ -49,42 +49,42 @@ class Date(Field):
|
|||
<select name=":'%s_year' % name" id=":'%s_year' % name">
|
||||
<option value="">-</option>
|
||||
<option for="year in years" value=":year"
|
||||
selected="contextObj.dateValueSelected(name, 'year', year, \
|
||||
selected="field.isSelected(contextObj, name, 'year', year, \
|
||||
rawValue)">:year</option>
|
||||
</select>
|
||||
|
||||
<!-- The icon for displaying the calendar popup -->
|
||||
<x if="widget['calendar']">
|
||||
<x if="field.calendar">
|
||||
<input type="hidden" id=":name" name=":name"/>
|
||||
<img id=":'%s_img' % name" src=":'%s/ui/calendar.gif' % appUrl"/>
|
||||
<script type="text/javascript">:contextObj.getCalendarInit(name, years)
|
||||
</script>
|
||||
<script type="text/javascript">:field.getJsInit(name, years)</script>
|
||||
</x>
|
||||
|
||||
<!-- Hour and minutes -->
|
||||
<x if="widget['format'] == 0">
|
||||
<select var="hours=range(0,24)"
|
||||
name=":'%s_hour' % name" id=":'%s_hour' % name">
|
||||
<x if="field.format == 0">
|
||||
<select var="hours=range(0,24)" name=":'%s_hour' % name"
|
||||
id=":'%s_hour' % name">
|
||||
<option value="">-</option>
|
||||
<x for="hour in hours">
|
||||
<option var="zHour=str(hour).zfill(2)" value=":zHour"
|
||||
selected=":contextObj.dateValueSelected(name, 'hour', hour, \
|
||||
rawValue)">:zHour</option></x>
|
||||
selected=":field.isSelected(contextObj, 'hour', hour, \
|
||||
rawValue)">:zHour</option>
|
||||
</x>
|
||||
</select> :
|
||||
<select var="minutes=range(0,60,5)"
|
||||
name=":'%s_minute' % name" id=":'%s_minute' % name">
|
||||
<select var="minutes=range(0,60,5)" name=":'%s_minute' % name"
|
||||
id=":'%s_minute' % name">
|
||||
<option value="">-</option>
|
||||
<x for="minute in minutes">
|
||||
<option var="zMinute=str(minute).zfill(2)" value=":zMinute"
|
||||
selected=":contextObj.dateValueSelected(name, 'minute', \
|
||||
minute, rawValue)">:zMinute</option></x>
|
||||
selected=":field.isSelected(contextObj, 'minute', minute,\
|
||||
rawValue)">:zMinute</option></x>
|
||||
</select>
|
||||
</x>
|
||||
</x>''')
|
||||
|
||||
pxSearch = Px('''
|
||||
<x var="years=range(widget['startYear'], widget['endYear']+1)">
|
||||
<label>:_(widget['labelId'])</label>
|
||||
<x var="years=range(field.startYear, field.endYear+1)">
|
||||
<label>:_(field.labelId)</label>
|
||||
<table>
|
||||
<!-- From -->
|
||||
<tr var="fromName='%s_from' % name;
|
||||
|
@ -106,14 +106,14 @@ class Date(Field):
|
|||
</select> /
|
||||
<select id=":yearFromName" name=":yearFromName">
|
||||
<option value="">--</option>
|
||||
<option for="value in range(widget['startYear'],widget['endYear']+1)"
|
||||
<option for="value in range(field.startYear, field.endYear+1)"
|
||||
value=":value">:value</option>
|
||||
</select>
|
||||
<!-- The icon for displaying the calendar popup -->
|
||||
<x if="widget['calendar']">
|
||||
<x if="field.calendar">
|
||||
<input type="hidden" id=":fromName" name=":fromName"/>
|
||||
<img id=":'%s_img' % fromName" src=":'%s/ui/calendar.gif' % appUrl"/>
|
||||
<script type="text/javascript">:tool.getCalendarInit(fromName, years)
|
||||
<script type="text/javascript">:field.getJsInit(fromName, years)
|
||||
</script>
|
||||
</x>
|
||||
</td>
|
||||
|
@ -139,14 +139,14 @@ class Date(Field):
|
|||
</select> /
|
||||
<select id=":yearToName" name=":yearToName">
|
||||
<option value="">--</option>
|
||||
<option for="value in range(widget['startYear'],widget['endYear']+1)"
|
||||
<option for="value in range(field.startYear, field.endYear+1)"
|
||||
value=":value">:value</option>
|
||||
</select>
|
||||
<!-- The icon for displaying the calendar popup -->
|
||||
<x if="widget['calendar']">
|
||||
<x if="widget.calendar">
|
||||
<input type="hidden" id=":toName" name=":toName"/>
|
||||
<img id=":'%s_img' % toName" src=":%s/ui/calendar.gif' % appUrl"/>
|
||||
<script type="text/javascript">:tool.getCalendarInit(toName, years)">
|
||||
<script type="text/javascript">:field.getJsInit(toName, years)">
|
||||
</script>
|
||||
</x>
|
||||
</td>
|
||||
|
@ -248,4 +248,30 @@ class Date(Field):
|
|||
return DateTime.DateTime(value)
|
||||
|
||||
def getIndexType(self): return 'DateIndex'
|
||||
|
||||
def isSelected(self, obj, fieldPart, dateValue, dbValue):
|
||||
'''When displaying this field, must the particular p_dateValue be
|
||||
selected in the sub-field p_fieldPart corresponding to the date
|
||||
part?'''
|
||||
# Get the value we must compare (from request or from database)
|
||||
rq = obj.REQUEST
|
||||
partName = '%s_%s' % (self.name, fieldPart)
|
||||
if rq.has_key(partName):
|
||||
compValue = rq.get(partName)
|
||||
if compValue.isdigit():
|
||||
compValue = int(compValue)
|
||||
else:
|
||||
compValue = dbValue
|
||||
if compValue:
|
||||
compValue = getattr(compValue, fieldPart)()
|
||||
# Compare the value
|
||||
return compValue == dateValue
|
||||
|
||||
def getJsInit(self, name, years):
|
||||
'''Gets the Javascript init code for displaying a calendar popup for
|
||||
this field, for an input named p_name (which can be different from
|
||||
self.name if, ie, it is a search field).'''
|
||||
return 'Calendar.setup({inputField: "%s", button: "%s_img", ' \
|
||||
'onSelect: onSelectDate, range:[%d,%d]});' % \
|
||||
(name, name, years[0], years[-1])
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
# ------------------------------------------------------------------------------
|
||||
import time, os.path, mimetypes
|
||||
from appy import Object
|
||||
from appy.fields import Field
|
||||
from appy.px import Px
|
||||
from appy.shared import utils as sutils
|
||||
|
@ -24,32 +25,32 @@ from appy.shared import utils as sutils
|
|||
class File(Field):
|
||||
|
||||
pxView = pxCell = Px('''
|
||||
<x var="info=contextObj.getFileInfo(value);
|
||||
empty=not info['size'];
|
||||
<x var="info=field.getFileInfo(value);
|
||||
empty=not info.size;
|
||||
imgSrc='%s/download?name=%s' % (contextObj.absolute_url(), name)">
|
||||
<x if="not empty and not widget['isImage']">
|
||||
<a href=":imgSrc">:info['filename']"</a> -
|
||||
<i class="discreet">'%sKb' % (info['size'] / 1024)"></i>
|
||||
<x if="not empty and not field.isImage">
|
||||
<a href=":imgSrc">:info.filename</a> -
|
||||
<i class="discreet">'%sKb' % (info.size / 1024)"></i>
|
||||
</x>
|
||||
<x if="not empty and widget['isImage']"><img src=":imgSrc"/></x>
|
||||
<x if="not empty and field.isImage"><img src=":imgSrc"/></x>
|
||||
<x if="empty">-</x>
|
||||
</x>''')
|
||||
|
||||
pxEdit = Px('''
|
||||
<x var="info=contextObj.getFileInfo(value);
|
||||
empty= not info['size'];
|
||||
<x var="info=field.getFileInfo(value);
|
||||
empty= not info.size;
|
||||
fName=q('%s_file' % name)">
|
||||
|
||||
<x if="not: empty">:widget['pxView']</x><br/>
|
||||
<x if="not empty">:field.pxView</x><br/>
|
||||
<x if="not empty">
|
||||
<!-- Keep the file unchanged. -->
|
||||
<input type="radio" value="nochange"
|
||||
checked=":(info['size'] != 0) and 'checked' or None"
|
||||
checked=":(info.size != 0) and 'checked' or None"
|
||||
name=":'%s_delete' % name" id=":'%s_nochange' % name"
|
||||
onclick=":'document.getElementById(%s).disabled=true' % fName"/>
|
||||
<label lfor=":'%s_nochange' % name">Keep the file unchanged</label><br/>
|
||||
<!-- Delete the file. -->
|
||||
<x if="not widget['required']">
|
||||
<x if="not field.required">
|
||||
<input type="radio" value="delete"
|
||||
name=":'%s_delete' % name" id=":'%s_delete' % name"
|
||||
onclick=":'document.getElementById(%s).disabled=true' % fName"/>
|
||||
|
@ -57,14 +58,14 @@ class File(Field):
|
|||
</x>
|
||||
<!-- Replace with a new file. -->
|
||||
<input type="radio" value=""
|
||||
checked=":(info['size'] == 0) and 'checked' or None"
|
||||
checked=":(info.size == 0) and 'checked' or None"
|
||||
name=":'%s_delete' % name" id=":'%s_upload' % name"
|
||||
onclick=":'document.getElementById(%s).disabled=false' % fName"/>
|
||||
<label lfor=":'%s_upload' % name">Replace it with a new file</label><br/>
|
||||
</x>
|
||||
<!-- The upload field. -->
|
||||
<input type="file" name=":'%s_file' % name" id=":'%s_file' % name"
|
||||
size=":widget['width']"/>
|
||||
size=":field.width"/>
|
||||
<script var="isDisabled=empty and 'false' or 'true'"
|
||||
type="text/javascript">:document.getElementById(%s).disabled=%s'%\
|
||||
(q(fName), q(isDisabled))">
|
||||
|
@ -223,4 +224,9 @@ class File(Field):
|
|||
if rq: action = rq.get('%s_delete' % self.name, None)
|
||||
if action == 'nochange': pass
|
||||
else: setattr(obj, self.name, None)
|
||||
|
||||
def getFileInfo(self, fileObject):
|
||||
'''Returns filename and size of p_fileObject.'''
|
||||
if not fileObject: return Object(filename='', size=0)
|
||||
return Object(filename=fileObject.filename, size=fileObject.size)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -31,24 +31,24 @@ class Float(Field):
|
|||
</x>''')
|
||||
|
||||
pxEdit = Px('''
|
||||
<input var="maxChars=widget['maxChars'] and widget['maxChars'] or ''"
|
||||
id=":name" name=":name" size=":widget['width']" maxlength=":maxChars"
|
||||
<input id=":name" name=":name" size=":field.width"
|
||||
maxlength=":field.maxChars"
|
||||
value=":inRequest and requestValue or value" type="text"/>''')
|
||||
|
||||
pxSearch = Px('''
|
||||
<x var="maxChars=widget['maxChars'] and widget['maxChars'] or ''">
|
||||
<label>:_(widget['labelId'])"></label><br/>
|
||||
<x>
|
||||
<label>:_(field.labelId)"></label><br/>
|
||||
<!-- From -->
|
||||
<x var="fromName='%s*float' % widgetName">
|
||||
<label lfor=":fromName">:_('search_from')"></label>
|
||||
<input type="text" name=":fromName" maxlength=":maxChars"
|
||||
value=":widget['sdefault'][0]" size=":widget['swidth]"/>
|
||||
<input type="text" name=":fromName" maxlength=":field.maxChars"
|
||||
value=":field.sdefault[0]" size=":field.swidth"/>
|
||||
</x>
|
||||
<!-- To -->
|
||||
<x var="toName='%s_to' % name">
|
||||
<label lfor=":toName">:_('search_to')</label>
|
||||
<input type="text" name=":toName" maxlength=":maxChars"
|
||||
value=":widget['sdefault'][1]" size="widget['swidth']"/>
|
||||
<input type="text" name=":toName" maxlength=":field.maxChars"
|
||||
value=":field.sdefault[1]" size="field.swidth"/>
|
||||
</x><br/>
|
||||
</x>''')
|
||||
|
||||
|
|
|
@ -28,25 +28,24 @@ class Integer(Field):
|
|||
</x>''')
|
||||
|
||||
pxEdit = Px('''
|
||||
<input var="maxChars=widget['maxChars'] and widget['maxChars'] or ''"
|
||||
id=":name" name=":name" size=":widget['width']"
|
||||
maxlength=":maxChars" value=":inRequest and requestValue or value"
|
||||
type="text"/>''')
|
||||
<input id=":name" name=":name" size=":field.width"
|
||||
maxlength=":field.maxChars"
|
||||
value=":inRequest and requestValue or value" type="text"/>''')
|
||||
|
||||
pxSearch = Px('''
|
||||
<x var="maxChars= widget['maxChars'] and widget['maxChars'] or ''">
|
||||
<label>:_(widget['labelId'])"></label><br/>
|
||||
<x>
|
||||
<label>:_(field.labelId)"></label><br/>
|
||||
<!-- From -->
|
||||
<x var="fromName='%s*int' % widgetName">
|
||||
<label lfor=":fromName">:_('search_from')</label>
|
||||
<input type="text" name=":fromName" maxlength=":maxChars"
|
||||
value=":widget['sdefault'][0]" size=":widget['swidth']"/>
|
||||
<input type="text" name=":fromName" maxlength=":field.maxChars"
|
||||
value=":field.sdefault[0]" size=":field.swidth"/>
|
||||
</x>
|
||||
<!-- To -->
|
||||
<x var="toName='%s_to' % name">
|
||||
<label lfor=":toName">:_('search_to')"></label>
|
||||
<input type="text" name=":toName" maxlength=":maxChars"
|
||||
value=":widget['sdefault'][1]" size=":widget['swidth']"/>
|
||||
<input type="text" name=":toName" maxlength=":field.maxChars"
|
||||
value=":field.sdefault[1]" size=":field.swidth"/>
|
||||
</x><br/>
|
||||
</x>''')
|
||||
|
||||
|
|
|
@ -27,12 +27,10 @@ class List(Field):
|
|||
# PX for rendering a single row.
|
||||
pxRow = Px('''
|
||||
<tr valign="top" style="(rowIndex==-1) and 'display: none' or ''">
|
||||
<td align="center" for="fieldInfo in widget['fieldsd']">
|
||||
<x var="widget=fieldInfo[1];
|
||||
<td align="center" for="info in field.fields">
|
||||
<x var="field=info[1];
|
||||
tagCss='noStyle';
|
||||
widgetName='%s*%d' % (widget['name'], rowIndex)">
|
||||
<x>:widget['pxView']</x>
|
||||
</x>
|
||||
widgetName='%s*%d' % (field.name, rowIndex)">:field.pxView</x>
|
||||
</td>
|
||||
<!-- Icon for removing the row -->
|
||||
<td if="layoutType=='edit'" align=":dright">
|
||||
|
@ -48,8 +46,7 @@ class List(Field):
|
|||
id=":'list_%s' % name" class="isEdit and 'grid' or 'list'">
|
||||
<!-- Header -->
|
||||
<tr valign="bottom">
|
||||
<th for="fieldInfo in widget['fieldsd']">::_(fieldInfo[1]['labelId'])
|
||||
</th>
|
||||
<th for="info in field.fields">::_(info[1].labelId)</th>
|
||||
<!-- Icon for adding a new row. -->
|
||||
<th if="isEdit">
|
||||
<img style="cursor:pointer" src=":'%s/ui/plus.png' % appUrl"
|
||||
|
@ -59,21 +56,20 @@ class List(Field):
|
|||
</tr>
|
||||
|
||||
<!-- Template row (edit only) -->
|
||||
<x var="rowIndex=-1" if="isEdit">:widget['pxRow']</x>
|
||||
<x var="rowIndex=-1" if="isEdit">:field.pxRow</x>
|
||||
<tr height="7px" if="isEdit"><td></td></tr>
|
||||
|
||||
<!-- Rows of data -->
|
||||
<x var="rows =inRequest and requestValue or value" for="row in rows">
|
||||
<x var="rowIndex=loop.row.nb">:widget['pxRow']</x>
|
||||
<x var="rows=inRequest and requestValue or value" for="row in rows">
|
||||
<x var="rowIndex=loop.row.nb">:field.pxRow</x>
|
||||
</x>
|
||||
</table>''')
|
||||
|
||||
pxView = pxCell = Px('''<x>:widget['pxTable']</x>''')
|
||||
pxView = pxCell = Px('''<x>:field.pxTable</x>''')
|
||||
pxEdit = Px('''
|
||||
<x>
|
||||
<!-- This input makes Appy aware that this field is in the request -->
|
||||
<input type="hidden" name=":name" value=""/>
|
||||
<x>:widget['pxTable']</x>
|
||||
<input type="hidden" name=":name" value=""/><x>:field.pxTable</x>
|
||||
</x>''')
|
||||
|
||||
pxSearch = ''
|
||||
|
|
|
@ -33,7 +33,6 @@ class Ogone(Field):
|
|||
pxView = pxCell = Px('''
|
||||
<x>
|
||||
<!-- var "value" is misused and contains the contact params for Ogone -->
|
||||
<p>:value</p>
|
||||
<!-- The form for sending the payment request to Ogone -->
|
||||
<form method="post" id="form1" name="form1" var="env=value['env']"
|
||||
action=":'https://secure.ogone.com/ncol/%s/orderstandard.asp'% env">
|
||||
|
|
|
@ -28,7 +28,7 @@ from appy.shared import utils as sutils
|
|||
class Pod(Field):
|
||||
'''A pod is a field allowing to produce a (PDF, ODT, Word, RTF...) document
|
||||
from data contained in Appy class and linked objects or anything you
|
||||
want to put in it. It uses appy.pod.'''
|
||||
want to put in it. It is the way gen uses pod.'''
|
||||
# Layout for rendering a POD field for exporting query results.
|
||||
rLayouts = {'view': Table('fl', width=None)}
|
||||
POD_ERROR = 'An error occurred while generating the document. Please ' \
|
||||
|
@ -38,14 +38,14 @@ class Pod(Field):
|
|||
pxView = pxCell = Px('''
|
||||
<x>
|
||||
<!-- Ask action -->
|
||||
<x if="widget['askAction']">
|
||||
<x var="doLabel='%s_askaction' % widget['labelId'];
|
||||
<x if="field.askAction">
|
||||
<x var="doLabel='%s_askaction' % field.labelId;
|
||||
chekboxId='%s_%s_cb' % (contextObj.UID(), name)">
|
||||
<input type="checkbox" name=":doLabel" id=":chekboxId"/>
|
||||
<label lfor=":chekboxId" class="discreet">:_(doLabel)"></label>
|
||||
</x>
|
||||
</x>
|
||||
<img for="podFormat in ztool.getPodInfo(contextObj, name)[1]"
|
||||
<img for="podFormat in field.getToolInfo(contextObj.appy())[1]"
|
||||
src=":'%s/ui/%s.png' % (appUrl, podFormat)"
|
||||
onclick=":'generatePodDocument(%s, %s, %s, %s)' % \
|
||||
(q(contextObj.UID()), q(name), q(podFormat), \
|
||||
|
|
196
fields/ref.py
196
fields/ref.py
|
@ -15,7 +15,7 @@
|
|||
# Appy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
import sys
|
||||
import sys, re
|
||||
from appy.fields import Field, No
|
||||
from appy.px import Px
|
||||
from appy.gen.layout import Table
|
||||
|
@ -37,16 +37,15 @@ class Ref(Field):
|
|||
# the URL for allowing to navigate from one object to the next/previous on
|
||||
# ui/view.
|
||||
pxObjectTitle = Px('''
|
||||
<x var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, \
|
||||
appyType['pageName'], loop.obj.nb + startNumber, totalNumber);
|
||||
navInfo=not appyType['isBack'] and navInfo or '';
|
||||
<x var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), field.name, \
|
||||
field.pageName, loop.obj.nb + startNumber, totalNumber);
|
||||
navInfo=not field.isBack and navInfo or '';
|
||||
cssClass=obj.getCssFor('title')">
|
||||
<x>::obj.getSupTitle(navInfo)</x>
|
||||
<a var="pageName=appyType['isBack'] and appyType['backd']['pageName'] or \
|
||||
'main';
|
||||
<a var="pageName=field.isBack and field.back.pageName or 'main';
|
||||
fullUrl=obj.getUrl(page=pageName, nav=navInfo)"
|
||||
href=":fullUrl" class=":cssClass">:(not includeShownInfo) and \
|
||||
obj.Title() or contextObj.getReferenceLabel(fieldName, obj.appy())
|
||||
obj.Title() or field.getReferenceLabel(obj.appy())
|
||||
</a><span name="subTitle" style=":showSubTitles and 'display:inline' or \
|
||||
'display:none'">::obj.getSubTitle()"</span>
|
||||
</x>''')
|
||||
|
@ -54,16 +53,16 @@ class Ref(Field):
|
|||
# This PX displays icons for triggering actions on a given referenced object
|
||||
# (edit, delete, etc).
|
||||
pxObjectActions = Px('''
|
||||
<table class="noStyle" var="isBack=appyType['isBack']">
|
||||
<table class="noStyle" var="isBack=field.isBack">
|
||||
<tr>
|
||||
<!-- Arrows for moving objects up or down -->
|
||||
<td if=":not isBack and (len(objs)>1) and changeOrder and canWrite">
|
||||
<x var="objectIndex=contextObj.getAppyRefIndex(fieldName, obj);
|
||||
<td if="not isBack and (len(objs)>1) and changeOrder and canWrite">
|
||||
<x var="objectIndex=field.getIndexOf(contextObj, obj);
|
||||
ajaxBaseCall=navBaseCall.replace('**v**','%s,%s,{%s:%s,%s:%s}'%\
|
||||
(q(startNumber), q('ChangeRefOrder'), q('refObjectUid'),
|
||||
q(obj.UID()), q('move'), q('**v**')))">
|
||||
<img if="objectIndex > 0" style="cursor:pointer"
|
||||
src=":'%s/ui/arrowUp.png' % $appUrl" title=":_('move_up')"
|
||||
src=":'%s/ui/arrowUp.png' % appUrl" title=":_('move_up')"
|
||||
onclick=":ajaxBaseCall.replace('**v**', 'up')"/><img
|
||||
style="cursor:pointer" if="objectIndex < (totalNumber-1)"
|
||||
src=":'%s/ui/arrowDown.png' % appUrl" title=":_('move_down')"
|
||||
|
@ -75,27 +74,25 @@ class Ref(Field):
|
|||
<x var="targetObj=obj">:targetObj.appy().pxTransitions</x>
|
||||
</td>
|
||||
<!-- Edit -->
|
||||
<td if="not appyType['noForm'] and obj.mayEdit() and appyType['delete']">
|
||||
<a var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, \
|
||||
appyType['pageName'], loop.obj.nb + startNumber, \
|
||||
totalNumber)"
|
||||
<td if="not field.noForm and obj.mayEdit() and field.delete">
|
||||
<a var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), field.name, \
|
||||
field.pageName, loop.obj.nb + startNumber, totalNumber)"
|
||||
href=":obj.getUrl(mode='edit', page='main', nav=navInfo)">
|
||||
<img src=":'%s/ui/edit.png' % appUrl" title=":_('object_edit')"/>
|
||||
</a>
|
||||
</td>
|
||||
<!-- Delete -->
|
||||
<td if="not isBack and appyType['delete'] and canWrite and \
|
||||
obj.mayDelete()">
|
||||
<td if="not isBack and field.delete and canWrite and obj.mayDelete()">
|
||||
<img style="cursor:pointer" title=":_('object_delete')"
|
||||
src=":'%s/ui/delete.png' % appUrl"
|
||||
onclick=":'onDeleteObject(%s)' % q(obj.UID())"/>
|
||||
</td>
|
||||
<!-- Unlink -->
|
||||
<td if="not isBack and appyType['unlink'] and canWrite">
|
||||
<td if="not isBack and field.unlink and canWrite">
|
||||
<img style="cursor:pointer" title=":_('object_unlink')"
|
||||
src=":'%s/ui/unlink.png' % appUrl"
|
||||
onclick=":'onUnlinkObject(%s,%s,%s)' % (q(contextObj.UID()), \
|
||||
q(appyType['name']), q(obj.UID()))"/>
|
||||
q(field.name), q(obj.UID()))"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>''')
|
||||
|
@ -106,21 +103,21 @@ class Ref(Field):
|
|||
<x if="showPlusIcon">
|
||||
<input type="button" class="button"
|
||||
var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), \
|
||||
fieldName, appyType['pageName'], 0, totalNumber);
|
||||
field.name, field.pageName, 0, totalNumber);
|
||||
formCall='window.location=%s' % \
|
||||
q('%s/do?action=Create&className=%s&nav=%s' % \
|
||||
(folder.absolute_url(), linkedPortalType, navInfo));
|
||||
formCall=not appyType['addConfirm'] and formCall or \
|
||||
formCall=not field.addConfirm and formCall or \
|
||||
'askConfirm(%s,%s,%s)' % (q('script'), q(formCall), \
|
||||
q(addConfirmMsg));
|
||||
noFormCall=navBaseCall.replace('**v**', \
|
||||
'%d,%s' % (startNumber, q('CreateWithoutForm')));
|
||||
noFormCall=not appyType['addConfirm'] and noFormCall or \
|
||||
noFormCall=not field.addConfirm and noFormCall or \
|
||||
'askConfirm(%s, %s, %s)' % (q('script'), q(noFormCall), \
|
||||
q(addConfirmMsg))"
|
||||
style=":'background-image: url(%s/ui/buttonAdd.png)' % appUrl"
|
||||
value=":_('add_ref')"
|
||||
onclick=":appyType['noForm'] and noFormCall or formCall"/>
|
||||
onclick=":field.noForm and noFormCall or formCall"/>
|
||||
</x>''')
|
||||
|
||||
# This PX displays, in a cell header from a ref table, icons for sorting the
|
||||
|
@ -128,8 +125,8 @@ class Ref(Field):
|
|||
pxSortIcons = Px('''
|
||||
<x var="ajaxBaseCall=navBaseCall.replace('**v**', '%s,%s,{%s:%s,%s:%s}' % \
|
||||
(q(startNumber), q('SortReference'), q('sortKey'), \
|
||||
q(widget['name']), q('reverse'), q('**v**')))"
|
||||
if="changeOrder and canWrite and ztool.isSortable(widget['name'], \
|
||||
q(field.name), q('reverse'), q('**v**')))"
|
||||
if="changeOrder and canWrite and ztool.isSortable(field.name, \
|
||||
objs[0].meta_type, 'ref')">
|
||||
<img style="cursor:pointer" src=":'%s/ui/sortAsc.png' % appUrl"
|
||||
onclick=":ajaxBaseCall.replace('**v**', 'False')"/>
|
||||
|
@ -140,29 +137,27 @@ class Ref(Field):
|
|||
# This PX is called by a XmlHttpRequest (or directly by pxView) for
|
||||
# displaying the referred objects of a reference field.
|
||||
pxViewContent = Px('''
|
||||
<div var="fieldName=req['fieldName'];
|
||||
appyType=contextObj.getAppyType(fieldName, asDict=True);
|
||||
innerRef=req.get('innerRef',False) == 'True';
|
||||
ajaxHookId=contextObj.UID() + fieldName;
|
||||
<div var="field=contextObj.getAppyType(req['fieldName']);
|
||||
innerRef=req.get('innerRef', False) == 'True';
|
||||
ajaxHookId=contextObj.UID() + field.name;
|
||||
startNumber=int(req.get('%s_startNumber' % ajaxHookId, 0));
|
||||
refObjects=contextObj.getAppyRefs(fieldName, startNumber);
|
||||
objs=refObjects['objects'];
|
||||
totalNumber=refObjects['totalNumber'];
|
||||
batchSize=refObjects['batchSize'];
|
||||
refObjects=field.getLinkedObjects(contextObj, startNumber);
|
||||
objs=refObjects.objects;
|
||||
totalNumber=refObjects.totalNumber;
|
||||
batchSize=refObjects.batchSize;
|
||||
folder=contextObj.getCreateFolder();
|
||||
linkedPortalType=ztool.getPortalType(appyType['klass']);
|
||||
canWrite=not appyType['isBack'] and \
|
||||
contextObj.allows(appyType['writePermission']);
|
||||
showPlusIcon=contextObj.mayAddReference(fieldName);
|
||||
atMostOneRef=(appyType['multiplicity'][1] == 1) and \
|
||||
linkedPortalType=ztool.getPortalType(field.klass);
|
||||
canWrite=not field.isBack and \
|
||||
contextObj.allows(field.writePermission);
|
||||
showPlusIcon=contextObj.mayAddReference(field.name);
|
||||
atMostOneRef=(field.multiplicity[1] == 1) and \
|
||||
(len(objs)<=1);
|
||||
addConfirmMsg=appyType['addConfirm'] and \
|
||||
_('%s_addConfirm' % appyType['labelId']) or '';
|
||||
addConfirmMsg=field.addConfirm and \
|
||||
_('%s_addConfirm' % field.labelId) or '';
|
||||
navBaseCall='askRefField(%s,%s,%s,%s,**v**)' % \
|
||||
(q(ajaxHookId), q(contextObj.absolute_url()), \
|
||||
q(fieldName), q(innerRef));
|
||||
changeOrder=contextObj.callField(fieldName, \
|
||||
'changeOrderEnabled', contextObj);
|
||||
q(field.name), q(innerRef));
|
||||
changeOrder=field.changeOrderEnabled(contextObj);
|
||||
showSubTitles=req.get('showSubTitles', 'true') == 'true'"
|
||||
id=":ajaxHookId">
|
||||
|
||||
|
@ -178,12 +173,12 @@ class Ref(Field):
|
|||
<!-- If there is no object -->
|
||||
<x if="not objs">
|
||||
<td class="discreet">:_('no_ref')</td>
|
||||
<td>:widget['pxAdd']</td>
|
||||
<td>:field.pxAdd</td>
|
||||
</x>
|
||||
<!-- If there is an object... -->
|
||||
<x if="objs">
|
||||
<x for="obj in objs">
|
||||
<td var="includeShownInfo=True">:widget['pxObjectTitle']</td>
|
||||
<td var="includeShownInfo=True">:field.pxObjectTitle</td>
|
||||
</x>
|
||||
</x>
|
||||
</tr>
|
||||
|
@ -194,15 +189,15 @@ class Ref(Field):
|
|||
<x if="not atMostOneRef">
|
||||
<div if="not innerRef or showPlusIcon" style="margin-bottom: 4px">
|
||||
(<x>:totalNumber</x>)
|
||||
<x>:widget['pxAdd']</x>
|
||||
<x>:field.pxAdd</x>
|
||||
<!-- The search button if field is queryable -->
|
||||
<input if="objs and appyType['queryable']" type="button" class="button"
|
||||
<input if="objs and field.queryable" type="button" class="button"
|
||||
style=":'background-image: url(%s/ui/buttonSearch.png)' % appUrl"
|
||||
value=":_('search_title')"
|
||||
onclick=":'window.location=%s' % \
|
||||
q('%s/ui/search?className=%s&ref=%s:%s' % \
|
||||
(ztool.absolute_url(), linkedPortalType, contextObj.UID(), \
|
||||
appyType['name']))"/>
|
||||
field.name))"/>
|
||||
</div>
|
||||
|
||||
<!-- Appy (top) navigation -->
|
||||
|
@ -216,17 +211,15 @@ class Ref(Field):
|
|||
<tr valign="bottom">
|
||||
<td>
|
||||
<!-- Show forward or backward reference(s) -->
|
||||
<table class="not innerRef and 'list' or '';
|
||||
width=innerRef and '100%' or \
|
||||
appyType['layouts']['view']['width']"
|
||||
var="columns=objs[0].getColumnsSpecifiers(\
|
||||
appyType['shownInfo'], dir)">
|
||||
<tr if="appyType['showHeaders']">
|
||||
<table class="not innerRef and 'list' or ''"
|
||||
width=":innerRef and '100%' or field.layouts['view']['width']"
|
||||
var="columns=objs[0].getColumnsSpecifiers(field.shownInfo, dir)">
|
||||
<tr if="field.showHeaders">
|
||||
<th for="column in columns" width=":column['width']"
|
||||
align="column['align']">
|
||||
<x var="widget=column['field']">
|
||||
<span>_(widget['labelId'])</span>
|
||||
<x>:widget['pxSortIcons']</x>
|
||||
<x var="field=column['field']">
|
||||
<span>_(field.labelId)</span>
|
||||
<x>:field.pxSortIcons</x>
|
||||
<x var="className=linkedPortalType">:contextObj.appy(\
|
||||
).pxShowDetails</x>
|
||||
</x>
|
||||
|
@ -237,18 +230,18 @@ class Ref(Field):
|
|||
class=":odd and 'even' or 'odd'">
|
||||
<td for="column in columns"
|
||||
width=":column['width']" align=":column['align']">
|
||||
<x var="widget=column['field']">
|
||||
<x var="field=column['field']">
|
||||
<!-- The "title" field -->
|
||||
<x if="python: widget['name'] == 'title'">
|
||||
<x>:widget['pxObjectTitle']</x>
|
||||
<div if="obj.mayAct()">:widget['pxObjectActions']</div>
|
||||
<x if="python: field.name == 'title'">
|
||||
<x>:field.pxObjectTitle</x>
|
||||
<div if="obj.mayAct()">:field.pxObjectActions</div>
|
||||
</x>
|
||||
<!-- Any other field -->
|
||||
<x if="widget['name'] != 'title'">
|
||||
<x if="field.name != 'title'">
|
||||
<x var="contextObj=obj;
|
||||
layoutType='cell';
|
||||
innerRef=True"
|
||||
if="obj.showField(widget['name'], layoutType='result')">
|
||||
if="obj.showField(field.name, layoutType='result')">
|
||||
<!-- use-macro="app/ui/widgets/show/macros/field"/-->
|
||||
</x>
|
||||
</x>
|
||||
|
@ -267,37 +260,35 @@ class Ref(Field):
|
|||
</div>''')
|
||||
|
||||
pxView = pxCell = Px('''
|
||||
<x var="x=req.set('fieldName', widget['name'])">:widget['pxViewContent']
|
||||
</x>''')
|
||||
<x var="x=req.set('fieldName', field.name)">:field.pxViewContent</x>''')
|
||||
|
||||
pxEdit = Px('''
|
||||
<x if="widget['link']"
|
||||
<x if="field.link"
|
||||
var="requestValue=req.get(name, []);
|
||||
inRequest=req.has_key(name);
|
||||
allObjects=contextObj.getSelectableAppyRefs(name);
|
||||
refUids=[o.UID() for o in contextObj.getAppyRefs(name)['objects']];
|
||||
allObjects=field.getSelectableObjects();
|
||||
uids=[o.UID() for o in field.getLinkedObjects(contextObj).objects];
|
||||
isBeingCreated=contextObj.isTemporary()">
|
||||
<select name=":name" size="isMultiple and widget['height'] or ''"
|
||||
<select name=":name" size="isMultiple and field.height or ''"
|
||||
multiple="isMultiple and 'multiple' or ''">
|
||||
<option value="" if="not isMultiple">:_('choose_a_value')"></option>
|
||||
<x for="refObj in allObjects">
|
||||
<option var="uid=contextObj.getReferenceUid(refObj)"
|
||||
<option var="uid=refObj.o.UID()"
|
||||
selected=":inRequest and (uid in requestValue) or \
|
||||
(uid in refUids)"
|
||||
value=":uid">:contextObj.getReferenceLabel(name, refObj)
|
||||
</option>
|
||||
(uid in uids)"
|
||||
value=":uid">:field.getReferenceLabel(refObj)</option>
|
||||
</x>
|
||||
</select>
|
||||
</x>''')
|
||||
|
||||
pxSearch = Px('''
|
||||
<x>
|
||||
<label lfor=":widgetName">:_(widget['labelId'])"></label><br/>
|
||||
<label lfor=":widgetName">:_(field.labelId)"></label><br/>
|
||||
<!-- The "and" / "or" radio buttons -->
|
||||
<x var="operName='o_%s' % name;
|
||||
orName='%s_or' % operName;
|
||||
andName='%s_and' % operName"
|
||||
if="widget['multiplicity'][1] != 1">
|
||||
if="field.multiplicity[1] != 1">
|
||||
<input type="radio" name=":operName" id=":orName"
|
||||
checked="checked" value="or"/>
|
||||
<label lfor=":orName">:_('search_or')"></label>
|
||||
|
@ -305,12 +296,12 @@ class Ref(Field):
|
|||
<label lfor=":andName">:_('search_and')"></label><br/>
|
||||
</x>
|
||||
<!-- The list of values -->
|
||||
<select name=":widgetName" size="widget['sheight']" multiple="multiple">
|
||||
<select name=":widgetName" size=":field.sheight" multiple="multiple">
|
||||
<x for="v in ztool.getSearchValues(name, className)">
|
||||
<option var="uid=v[0];
|
||||
title=ztool.getReferenceLabel(name, v[1], className)"
|
||||
title=field.getReferenceLabel(v[1])"
|
||||
value=":uid"
|
||||
title=":title">:ztool.truncateValue(title, widget['swidth'])">
|
||||
title=":title">:ztool.truncateValue(title, field.swidth)">
|
||||
</option>
|
||||
</x>
|
||||
</select>
|
||||
|
@ -482,6 +473,14 @@ class Ref(Field):
|
|||
if someObjects: return res
|
||||
return res.objects
|
||||
|
||||
def getLinkedObjects(self, obj, startNumber=None):
|
||||
'''Gets the objects linked to p_obj via this Ref field. If p_startNumber
|
||||
is None, all linked objects are returned. If p_startNumber is a
|
||||
number, self.maxPerPage objects will be returned, starting at
|
||||
p_startNumber.'''
|
||||
return self.getValue(obj, type='zobjects', someObjects=True,
|
||||
startNumber=startNumber)
|
||||
|
||||
def getFormattedValue(self, obj, value, showChanges=False):
|
||||
return value
|
||||
|
||||
|
@ -650,6 +649,47 @@ class Ref(Field):
|
|||
else:
|
||||
return self.callMethod(obj, self.changeOrder)
|
||||
|
||||
def getSelectableObjects(self, contextObj):
|
||||
'''This method returns the list of all objects that can be selected to
|
||||
be linked as references to p_contextObj via p_self.'''
|
||||
if not self.select:
|
||||
# No select method has been defined: we must retrieve all objects
|
||||
# of the referred type that the user is allowed to access.
|
||||
return contextObj.appy().search(self.klass)
|
||||
else:
|
||||
return self.select(contextObj.appy())
|
||||
|
||||
xhtmlToText = re.compile('<.*?>', re.S)
|
||||
def getReferenceLabel(self, refObject):
|
||||
'''p_self must have link=True. I need to display, on an edit view, the
|
||||
p_refObject in the listbox that will allow the user to choose which
|
||||
object(s) to link through the Ref. The information to display may
|
||||
only be the object title or more if self.shownInfo is used.'''
|
||||
res = ''
|
||||
for fieldName in self.shownInfo:
|
||||
refType = refObject.o.getAppyType(fieldName)
|
||||
value = getattr(refObject, fieldName)
|
||||
value = refType.getFormattedValue(refObject.o, value)
|
||||
if refType.type == 'String':
|
||||
if refType.format == 2:
|
||||
value = self.xhtmlToText.sub(' ', value)
|
||||
elif type(value) in sequenceTypes:
|
||||
value = ', '.join(value)
|
||||
prefix = ''
|
||||
if res:
|
||||
prefix = ' | '
|
||||
res += prefix + value
|
||||
maxWidth = self.width or 30
|
||||
if len(res) > maxWidth:
|
||||
res = res[:maxWidth-2] + '...'
|
||||
return res
|
||||
|
||||
def getIndexOf(self, obj, refObj):
|
||||
'''Gets the position of p_refObj within this field on p_obj.'''
|
||||
uids = getattr(obj.aq_base, self.name, None)
|
||||
if not uids: raise IndexError()
|
||||
return uids.index(refObj.UID())
|
||||
|
||||
def autoref(klass, field):
|
||||
'''klass.field is a Ref to p_klass. This kind of auto-reference can't be
|
||||
declared in the "normal" way, like this:
|
||||
|
|
183
fields/string.py
183
fields/string.py
|
@ -20,6 +20,7 @@ import re, random
|
|||
from appy.gen.layout import Table
|
||||
from appy.gen.indexer import XhtmlTextExtractor
|
||||
from appy.fields import Field
|
||||
from appy.px import Px
|
||||
from appy.shared.data import countries
|
||||
from appy.shared.xml_parser import XhtmlCleaner
|
||||
from appy.shared.diff import HtmlDiff
|
||||
|
@ -71,6 +72,118 @@ class String(Field):
|
|||
URL = c('(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*(\.[a-z]{2,5})?' \
|
||||
'(([0-9]{1,5})?\/.*)?')
|
||||
|
||||
pxView = Px('''
|
||||
<x var="fmt=field.format; isUrl=field.isUrl;
|
||||
mayAjaxEdit=not showChanges and field.inlineEdit and \
|
||||
contextObj.mayEdit(field.writePermission)">
|
||||
<x if="fmt in (0, 3)">
|
||||
<ul if="value and isMultiple">
|
||||
<li for="sv in value"><i>::sv</i></li>
|
||||
</ul>
|
||||
<x if="value and not isMultiple">
|
||||
<!-- A password -->
|
||||
<x if="fmt == 3">********</x>
|
||||
<!-- A URL -->
|
||||
<a if="(fmt != 3) and isUrl" target="_blank" href=":value">:value</a>
|
||||
<!-- Any other value -->
|
||||
<x if="(fmt != 3) and not isUrl">::value</x>
|
||||
</x>
|
||||
</x>
|
||||
<!-- Unformatted text -->
|
||||
<x if="value and (fmt == 1)">::contextObj.formatText(value, format='html')
|
||||
</x>
|
||||
<!-- XHTML text -->
|
||||
<x if="value and (fmt == 2)">
|
||||
<div if="not mayAjaxEdit" class="xhtml">::value</div>
|
||||
<div if="mayAjaxEdit" class="xhtml" contenteditable="true"
|
||||
id=":'%s_%s_ck' % (contextObj.UID(), name)">::value</div>
|
||||
<script if="mayAjaxEdit">:field.getJsInlineInit(contextObj)"></script>
|
||||
</x>
|
||||
<input type="hidden" if="masterCss" class=":masterCss" value=":rawValue"
|
||||
name=":name" id=":name"/>
|
||||
</x>''')
|
||||
|
||||
pxEdit = Px('''
|
||||
<x var="fmt=field.format;
|
||||
isSelect=field.isSelect;
|
||||
isMaster=field.slaves;
|
||||
isOneLine=fmt in (0,3,4)">
|
||||
<x if="isSelect">
|
||||
<select var="possibleValues=field.getPossibleValues(contextObj, \
|
||||
withTranslations=True, withBlankValue=True)"
|
||||
name=":name" id=":name" class=":masterCss"
|
||||
multiple=":isMultiple and 'multiple' or ''"
|
||||
onchange=":isMaster and 'updateSlaves(this)' or ''"
|
||||
size=":isMultiple and field.height or 1">
|
||||
<option for="val in possibleValues" value=":val[0]"
|
||||
selected=":field.isSelected(contextObj, val[0], rawValue)"
|
||||
title=":val[1]">:ztool.truncateValue(val[1], field.width)">
|
||||
</option>
|
||||
</select>
|
||||
</x>
|
||||
<x if="isOneLine and not isSelect">
|
||||
<input id=":name" name=":name" size=":field.width"
|
||||
maxlength=":field.maxChars"
|
||||
value=":inRequest and requestValue or value"
|
||||
style=":'text-transform:%s' % field.transform"
|
||||
type=":(fmt == 3) and 'password' or 'text'"/>
|
||||
<!-- Display a captcha if required -->
|
||||
<span if="fmt == 4">:_('captcha_text', \
|
||||
mapping=field.getCaptchaChallenge(req.SESSION))
|
||||
</span>
|
||||
</x>
|
||||
<x if="fmt in (1,2)">
|
||||
<textarea id=":name" name=":name" cols=":field.width"
|
||||
class=":(fmt == 2) and ('rich_%s' % name) or ''"
|
||||
style=":'text-transform:%s' % field.transform"
|
||||
rows=":field.height">:inRequest and requestValue or value
|
||||
</textarea>
|
||||
<script if="fmt == 2"
|
||||
type="text/javascript">:field.getJsInit(contextObj)</script>
|
||||
</x>
|
||||
</x>''')
|
||||
|
||||
pxCell = Px('''
|
||||
<x var="multipleValues=value and isMultiple">
|
||||
<x if="multipleValues">:', '.join(value)"></x>
|
||||
<x if="not multipleValues">:field.pxView</x>
|
||||
</x>''')
|
||||
|
||||
pxSearch = Px('''
|
||||
<x>
|
||||
<label lfor="widgetName">:_(field.labelId)"></label><br/>
|
||||
<!-- Show a simple search field for most String fields -->
|
||||
<x if="not field.isSelect">
|
||||
<input type="text" maxlength=":field.maxChars" size=":field.swidth"
|
||||
name=":'%s*string-%s' % (widgetName, field.transform)"
|
||||
style=":'text-transform:%s' % field.transform"
|
||||
value=":field.sdefault"/>
|
||||
</x>
|
||||
<!-- Show a multi-selection box for fields whose validator defines a list
|
||||
of values, with a "AND/OR" checkbox. -->
|
||||
<x if="field.isSelect">
|
||||
<!-- The "and" / "or" radio buttons -->
|
||||
<x var="operName='o_%s' % name;
|
||||
orName='%s_or' % operName;
|
||||
andName='%s_and' % operName"
|
||||
if="field.multiplicity[1] != 1">
|
||||
<input type="radio" name=":operName" id=":orName" checked="checked"
|
||||
value="or"/>
|
||||
<label lfor=":orName">:_('search_or')</label>
|
||||
<input type="radio" name=":operName" id=":andName" value="and"/>
|
||||
<label lfor=":andName">:_('search_and')"></label><br/>
|
||||
</x>
|
||||
<!-- The list of values -->
|
||||
<select var="preSelected=field.sdefault"
|
||||
name=":widgetName" size=":field.sheight" multiple="multiple">
|
||||
<option for="v in field.getPossibleValues(ztool, withTranslations=True,\
|
||||
withBlankValue=False, className=className)"
|
||||
selected=":v[0] in preSelected" value=":v[0]"
|
||||
title=":v[1]">ztool.truncateValue(v[1], field.swidth)</option>
|
||||
</select>
|
||||
</x><br/>
|
||||
</x>''')
|
||||
|
||||
# Some predefined functions that may also be used as validators
|
||||
@staticmethod
|
||||
def _MODULO_97(obj, value, complement=False):
|
||||
|
@ -352,14 +465,16 @@ class String(Field):
|
|||
if res in self.emptyValuesCatalogIgnored: res = ' '
|
||||
return res
|
||||
|
||||
def getPossibleValues(self,obj,withTranslations=False,withBlankValue=False):
|
||||
'''Returns the list of possible values for this field if it is a
|
||||
selection field. If p_withTranslations is True,
|
||||
instead of returning a list of string values, the result is a list
|
||||
of tuples (s_value, s_translation). If p_withBlankValue is True, a
|
||||
blank value is prepended to the list, excepted if the type is
|
||||
multivalued.'''
|
||||
if not self.isSelect: raise 'This field is not a selection.'
|
||||
def getPossibleValues(self, obj, withTranslations=False,
|
||||
withBlankValue=False, className=None):
|
||||
'''Returns the list of possible values for this field (only for fields
|
||||
with self.isSelect=True). If p_withTranslations is True, instead of
|
||||
returning a list of string values, the result is a list of tuples
|
||||
(s_value, s_translation). If p_withBlankValue is True, a blank value
|
||||
is prepended to the list, excepted if the type is multivalued. If
|
||||
p_className is given, p_obj is the tool and, if we need an instance
|
||||
of p_className, we will need to use obj.executeQuery to find one.'''
|
||||
if not self.isSelect: raise Exception('This field is not a selection.')
|
||||
if isinstance(self.validator, Selection):
|
||||
# We need to call self.methodName for getting the (dynamic) values.
|
||||
# If methodName begins with _appy_, it is a special Appy method:
|
||||
|
@ -381,6 +496,15 @@ class String(Field):
|
|||
if methodName.startswith('tool:'):
|
||||
obj = obj.getTool()
|
||||
methodName = methodName[5:]
|
||||
else:
|
||||
# We must call on p_obj. But if we have something in
|
||||
# p_className, p_obj is the tool and not an instance of
|
||||
# p_className as required. So find such an instance.
|
||||
if className:
|
||||
brains = obj.executeQuery(className, maxResults=1,
|
||||
brainsOnly=True)
|
||||
if brains:
|
||||
obj = brains[0].getObject()
|
||||
# Do we need to call the method on the object or on the wrapper?
|
||||
if methodName.startswith('_appy_'):
|
||||
exec 'res = obj.%s(*args)' % methodName
|
||||
|
@ -503,4 +627,47 @@ class String(Field):
|
|||
'''Generates a password (we recycle here the captcha challenge
|
||||
generator).'''
|
||||
return self.getCaptchaChallenge({})['text']
|
||||
|
||||
def getJsInit(self, obj):
|
||||
'''Gets the Javascript init code for displaying a rich editor for this
|
||||
field (rich field only).'''
|
||||
# Define the attributes that will initialize the ckeditor instance for
|
||||
# this field.
|
||||
ckAttrs = {'toolbar': 'Appy',
|
||||
'format_tags': '%s' % ';'.join(self.styles)}
|
||||
if self.width: ckAttrs['width'] = self.width
|
||||
if self.allowImageUpload:
|
||||
ckAttrs['filebrowserUploadUrl'] = '%s/upload' % obj.absolute_url()
|
||||
ck = []
|
||||
for k, v in ckAttrs.iteritems():
|
||||
if isinstance(v, int): sv = str(v)
|
||||
else: sv = '"%s"' % v
|
||||
ck.append('%s: %s' % (k, sv))
|
||||
return 'CKEDITOR.replace("%s", {%s})' % (name, ', '.join(ck))
|
||||
|
||||
def getJsInlineInit(self, obj):
|
||||
'''Gets the Javascript init code for enabling inline edition of this
|
||||
field (rich text only).'''
|
||||
uid = obj.UID()
|
||||
return "CKEDITOR.disableAutoInline = true;\n" \
|
||||
"CKEDITOR.inline('%s_%s_ck', {on: {blur: " \
|
||||
"function( event ) { var data = event.editor.getData(); " \
|
||||
"askAjaxChunk('%s_%s','POST','%s','page','saveField', "\
|
||||
"{'fieldName':'%s', 'fieldContent': encodeURIComponent(data)}, "\
|
||||
"null, evalInnerScripts);}}});"% \
|
||||
(uid, self.name, uid, self.name, obj.absolute_url(), self.name)
|
||||
|
||||
def isSelected(self, obj, vocabValue, dbValue):
|
||||
'''When displaying a selection box (only for fields with a validator
|
||||
being a list), must the _vocabValue appear as selected?'''
|
||||
rq = obj.REQUEST
|
||||
# Get the value we must compare (from request or from database)
|
||||
if rq.has_key(self.name):
|
||||
compValue = rq.get(self.name)
|
||||
else:
|
||||
compValue = dbValue
|
||||
# Compare the value
|
||||
if type(compValue) in sutils.sequenceTypes:
|
||||
return vocabValue in compValue
|
||||
return vocabValue == compValue
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -1393,24 +1393,10 @@ class BaseMixin:
|
|||
|
||||
def getPossibleValues(self, name, withTranslations, withBlankValue,
|
||||
className=None):
|
||||
'''Gets the possible values for field named p_name. This field must be a
|
||||
String with isSelection()=True. If p_withTranslations is True,
|
||||
instead of returning a list of string values, the result is a list
|
||||
of tuples (s_value, s_translation). If p_withBlankValue is True, a
|
||||
blank value is prepended to the list. If no p_className is defined,
|
||||
the field is supposed to belong to self's class.'''
|
||||
appyType = self.getAppyType(name, className=className)
|
||||
if className:
|
||||
# We need an instance of className, but self can be an instance of
|
||||
# another class. So here we will search such an instance.
|
||||
brains = self.executeQuery(className, maxResults=1, brainsOnly=True)
|
||||
if brains:
|
||||
obj = brains[0].getObject()
|
||||
else:
|
||||
obj = self
|
||||
else:
|
||||
obj = self
|
||||
return appyType.getPossibleValues(obj, withTranslations, withBlankValue)
|
||||
'''See docstring of String.getPossibleValues.'''
|
||||
field = self.getAppyType(name, className=className)
|
||||
return field.getPossibleValues(self, withTranslations, withBlankValue,
|
||||
className=className)
|
||||
|
||||
def getCaptchaChallenge(self, name):
|
||||
return self.getAppyType(name).getCaptchaChallenge(self.REQUEST.SESSION)
|
||||
|
|
Loading…
Reference in a new issue