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