[gen] Allow for ajax-based master-slave relationships within the search screen for Ref fields.
This commit is contained in:
parent
584e38abef
commit
6d6c842f12
|
@ -51,15 +51,17 @@ class Field:
|
||||||
pxRender = Px('''
|
pxRender = Px('''
|
||||||
<x var="showChanges=showChanges|req.get('showChanges',False);
|
<x var="showChanges=showChanges|req.get('showChanges',False);
|
||||||
layoutType=layoutType|req.get('layoutType');
|
layoutType=layoutType|req.get('layoutType');
|
||||||
|
isSearch = layoutType == 'search';
|
||||||
layout=field.layouts[layoutType];
|
layout=field.layouts[layoutType];
|
||||||
name=fieldName|field.name;
|
name=fieldName|field.name;
|
||||||
|
widgetName = isSearch and ('w_%s' % name) or name;
|
||||||
sync=field.sync[layoutType];
|
sync=field.sync[layoutType];
|
||||||
outerValue=value|None;
|
outerValue=value|None;
|
||||||
rawValue=zobj.getFieldValue(name, onlyIfSync=True, \
|
rawValue=not isSearch and zobj.getFieldValue(name, \
|
||||||
layoutType=layoutType, \
|
onlyIfSync=True, layoutType=layoutType, outerValue=outerValue);
|
||||||
outerValue=outerValue);
|
value=not isSearch and \
|
||||||
value=zobj.getFormattedFieldValue(name, rawValue, showChanges);
|
field.getFormattedValue(zobj, rawValue, showChanges);
|
||||||
requestValue=zobj.getRequestFieldValue(name);
|
requestValue=not isSearch and zobj.getRequestFieldValue(name);
|
||||||
inRequest=req.has_key(name);
|
inRequest=req.has_key(name);
|
||||||
error=req.get('%s_error' % name);
|
error=req.get('%s_error' % name);
|
||||||
isMultiple=(field.multiplicity[1] == None) or \
|
isMultiple=(field.multiplicity[1] == None) or \
|
||||||
|
@ -68,6 +70,7 @@ class Field:
|
||||||
slaveCss=field.getSlaveCss();
|
slaveCss=field.getSlaveCss();
|
||||||
tagCss=tagCss|'';
|
tagCss=tagCss|'';
|
||||||
tagCss=('%s %s' % (slaveCss, tagCss)).strip();
|
tagCss=('%s %s' % (slaveCss, tagCss)).strip();
|
||||||
|
zobj=zobj or ztool;
|
||||||
tagId='%s_%s' % (zobj.UID(), name);
|
tagId='%s_%s' % (zobj.UID(), name);
|
||||||
tagName=field.master and 'slave' or '';
|
tagName=field.master and 'slave' or '';
|
||||||
layoutTarget=field">:tool.pxLayoutedObject</x>''')
|
layoutTarget=field">:tool.pxLayoutedObject</x>''')
|
||||||
|
@ -345,8 +348,8 @@ class Field:
|
||||||
'''Creates a dictionary indicating, for every layout type, if the field
|
'''Creates a dictionary indicating, for every layout type, if the field
|
||||||
value must be retrieved synchronously or not.'''
|
value must be retrieved synchronously or not.'''
|
||||||
if isinstance(sync, bool):
|
if isinstance(sync, bool):
|
||||||
sync = {'edit': sync, 'view': sync, 'cell': sync}
|
sync = {'edit': sync, 'view': sync, 'cell': sync, 'search': sync}
|
||||||
for layoutType in ('edit', 'view', 'cell'):
|
for layoutType in ('edit', 'view', 'search', 'cell'):
|
||||||
if layoutType not in sync:
|
if layoutType not in sync:
|
||||||
sync[layoutType] = False
|
sync[layoutType] = False
|
||||||
return sync
|
return sync
|
||||||
|
@ -405,9 +408,13 @@ class Field:
|
||||||
for layoutType in layouts.iterkeys():
|
for layoutType in layouts.iterkeys():
|
||||||
if isinstance(layouts[layoutType], basestring):
|
if isinstance(layouts[layoutType], basestring):
|
||||||
layouts[layoutType] = Table(layouts[layoutType])
|
layouts[layoutType] = Table(layouts[layoutType])
|
||||||
# Derive "view" and "cell" layouts from the "edit" layout when relevant
|
# Derive "view", "search" and "cell" layouts from the "edit" layout
|
||||||
|
# when relevant.
|
||||||
if 'view' not in layouts:
|
if 'view' not in layouts:
|
||||||
layouts['view'] = Table(other=layouts['edit'], derivedType='view')
|
layouts['view'] = Table(other=layouts['edit'], derivedType='view')
|
||||||
|
if 'search' not in layouts:
|
||||||
|
layouts['search'] = Table(other=layouts['view'],
|
||||||
|
derivedType='search')
|
||||||
# Create the "cell" layout from the 'view' layout if not specified.
|
# Create the "cell" layout from the 'view' layout if not specified.
|
||||||
if 'cell' not in layouts:
|
if 'cell' not in layouts:
|
||||||
layouts['cell'] = Table(other=layouts['view'], derivedType='cell')
|
layouts['cell'] = Table(other=layouts['view'], derivedType='cell')
|
||||||
|
@ -587,14 +594,16 @@ class Field:
|
||||||
res += '+'
|
res += '+'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getOnChange(self, zobj, layoutType):
|
def getOnChange(self, zobj, layoutType, className=None):
|
||||||
'''When this field is a master, this method computes the call to the
|
'''When this field is a master, this method computes the call to the
|
||||||
Javascript function that will be called when its value changes (in
|
Javascript function that will be called when its value changes (in
|
||||||
order to update slaves).'''
|
order to update slaves).'''
|
||||||
if not self.slaves: return ''
|
if not self.slaves: return ''
|
||||||
q = zobj.getTool().quote
|
q = zobj.getTool().quote
|
||||||
return 'updateSlaves(this,null,%s,%s)' % \
|
# When the field is on a search screen, we need p_className.
|
||||||
(q(zobj.absolute_url()), q(layoutType))
|
cName = className and (',%s' % q(className)) or ''
|
||||||
|
return 'updateSlaves(this,null,%s,%s,null,null%s)' % \
|
||||||
|
(q(zobj.absolute_url()), q(layoutType), cName)
|
||||||
|
|
||||||
def isEmptyValue(self, value, obj=None):
|
def isEmptyValue(self, value, obj=None):
|
||||||
'''Returns True if the p_value must be considered as an empty value.'''
|
'''Returns True if the p_value must be considered as an empty value.'''
|
||||||
|
|
|
@ -38,9 +38,7 @@ class Boolean(Field):
|
||||||
value=":isChecked and 'True' or 'False'"/>
|
value=":isChecked and 'True' or 'False'"/>
|
||||||
</x>''')
|
</x>''')
|
||||||
|
|
||||||
pxSearch = Px('''
|
pxSearch = Px('''<x var="typedWidget='%s*bool' % widgetName">
|
||||||
<x var="typedWidget='%s*bool' % widgetName">
|
|
||||||
<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>
|
||||||
|
@ -53,8 +51,7 @@ class Boolean(Field):
|
||||||
<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>''')
|
|
||||||
|
|
||||||
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
||||||
show=True, page='main', group=None, layouts = None, move=0,
|
show=True, page='main', group=None, layouts = None, move=0,
|
||||||
|
|
|
@ -38,11 +38,9 @@ class Computed(Field):
|
||||||
</div>
|
</div>
|
||||||
</x>''')
|
</x>''')
|
||||||
|
|
||||||
pxSearch = Px('''<x>
|
pxSearch = Px('''
|
||||||
<label lfor=":name">:field.labelId</label><br/>
|
|
||||||
<input type="text" name=":'%s*string' % name" maxlength=":field.maxChars"
|
<input type="text" name=":'%s*string' % name" maxlength=":field.maxChars"
|
||||||
size=":field.width" value=":field.sdefault"/>
|
size=":field.width" value=":field.sdefault"/>''')
|
||||||
</x>''')
|
|
||||||
|
|
||||||
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
||||||
show=('view', 'result'), page='main', group=None,
|
show=('view', 'result'), page='main', group=None,
|
||||||
|
|
|
@ -81,10 +81,7 @@ class Date(Field):
|
||||||
</x>
|
</x>
|
||||||
</x>''')
|
</x>''')
|
||||||
|
|
||||||
pxSearch = Px('''
|
pxSearch = Px('''<table var="years=range(field.startYear, field.endYear+1)">
|
||||||
<x var="years=range(field.startYear, field.endYear+1)">
|
|
||||||
<label>:_(field.labelId)</label>
|
|
||||||
<table>
|
|
||||||
<!-- From -->
|
<!-- From -->
|
||||||
<tr var="fromName='%s_from' % name;
|
<tr var="fromName='%s_from' % name;
|
||||||
dayFromName='%s_from_day' % name;
|
dayFromName='%s_from_day' % name;
|
||||||
|
@ -150,8 +147,7 @@ class Date(Field):
|
||||||
</x>
|
</x>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>''')
|
||||||
</x>''')
|
|
||||||
|
|
||||||
# Required CSS and Javascript files for this type.
|
# Required CSS and Javascript files for this type.
|
||||||
cssFiles = {'edit': ('jscalendar/calendar-blue.css',)}
|
cssFiles = {'edit': ('jscalendar/calendar-blue.css',)}
|
||||||
|
|
|
@ -35,8 +35,7 @@ class Float(Field):
|
||||||
maxlength=":field.maxChars"
|
maxlength=":field.maxChars"
|
||||||
value=":inRequest and requestValue or value" type="text"/>''')
|
value=":inRequest and requestValue or value" type="text"/>''')
|
||||||
|
|
||||||
pxSearch = Px('''<x>
|
pxSearch = Px('''
|
||||||
<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>
|
||||||
|
@ -48,8 +47,7 @@ class Float(Field):
|
||||||
<label lfor=":toName">:_('search_to')</label>
|
<label lfor=":toName">:_('search_to')</label>
|
||||||
<input type="text" name=":toName" maxlength=":field.maxChars"
|
<input type="text" name=":toName" maxlength=":field.maxChars"
|
||||||
value=":field.sdefault[1]" size="field.swidth"/>
|
value=":field.sdefault[1]" size="field.swidth"/>
|
||||||
</x><br/>
|
</x><br/>''')
|
||||||
</x>''')
|
|
||||||
|
|
||||||
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
||||||
show=True, page='main', group=None, layouts=None, move=0,
|
show=True, page='main', group=None, layouts=None, move=0,
|
||||||
|
|
|
@ -32,8 +32,7 @@ class Integer(Field):
|
||||||
maxlength=":field.maxChars"
|
maxlength=":field.maxChars"
|
||||||
value=":inRequest and requestValue or value" type="text"/>''')
|
value=":inRequest and requestValue or value" type="text"/>''')
|
||||||
|
|
||||||
pxSearch = Px('''<x>
|
pxSearch = Px('''
|
||||||
<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>
|
||||||
|
@ -45,8 +44,7 @@ class Integer(Field):
|
||||||
<label lfor=":toName">:_('search_to')</label>
|
<label lfor=":toName">:_('search_to')</label>
|
||||||
<input type="text" name=":toName" maxlength=":field.maxChars"
|
<input type="text" name=":toName" maxlength=":field.maxChars"
|
||||||
value=":field.sdefault[1]" size=":field.swidth"/>
|
value=":field.sdefault[1]" size=":field.swidth"/>
|
||||||
</x><br/>
|
</x><br/>''')
|
||||||
</x>''')
|
|
||||||
|
|
||||||
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
def __init__(self, validator=None, multiplicity=(0,1), default=None,
|
||||||
show=True, page='main', group=None, layouts=None, move=0,
|
show=True, page='main', group=None, layouts=None, move=0,
|
||||||
|
|
|
@ -282,21 +282,20 @@ class Ref(Field):
|
||||||
|
|
||||||
pxEdit = Px('''
|
pxEdit = Px('''
|
||||||
<select if="field.link"
|
<select if="field.link"
|
||||||
var2="zobjects=field.getSelectableObjects(obj);
|
var2="objects=field.getPossibleValues(obj);
|
||||||
uids=[o.UID() for o in \
|
uids=[o.UID() for o in \
|
||||||
field.getLinkedObjects(zobj).objects]"
|
field.getLinkedObjects(zobj).objects]"
|
||||||
name=":name" id=":name" size=":isMultiple and field.height or ''"
|
name=":name" id=":name" size=":isMultiple and field.height or ''"
|
||||||
onchange=":field.getOnChange(zobj, layoutType)"
|
onchange=":field.getOnChange(zobj, layoutType)"
|
||||||
multiple=":isMultiple">
|
multiple=":isMultiple">
|
||||||
<option value="" if="not isMultiple">:_('choose_a_value')</option>
|
<option value="" if="not isMultiple">:_('choose_a_value')</option>
|
||||||
<option for="ztied in zobjects" var2="uid=ztied.o.UID()"
|
<option for="tied in objects" var2="uid=tied.uid"
|
||||||
selected=":inRequest and (uid in requestValue) or \
|
selected=":inRequest and (uid in requestValue) or \
|
||||||
(uid in uids)"
|
(uid in uids)"
|
||||||
value=":uid">:field.getReferenceLabel(ztied)</option>
|
value=":uid">:field.getReferenceLabel(tied)</option>
|
||||||
</select>''')
|
</select>''')
|
||||||
|
|
||||||
pxSearch = Px('''<x>
|
pxSearch = Px('''
|
||||||
<label lfor=":widgetName">:_(field.labelId)</label><br/>
|
|
||||||
<!-- The "and" / "or" radio buttons -->
|
<!-- The "and" / "or" radio buttons -->
|
||||||
<x if="field.multiplicity[1] != 1"
|
<x if="field.multiplicity[1] != 1"
|
||||||
var2="operName='o_%s' % name;
|
var2="operName='o_%s' % name;
|
||||||
|
@ -309,12 +308,14 @@ 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=":field.sheight" multiple="multiple">
|
<select var="objects=field.getPossibleValues(tool);
|
||||||
<option for="v in ztool.getSearchValues(name, className)"
|
selectAll='masterValues' in req"
|
||||||
var2="uid=v[0]; title=field.getReferenceLabel(v[1])" value=":uid"
|
name=":widgetName" size=":field.sheight" multiple="multiple"
|
||||||
title=":title">:ztool.truncateValue(title,field.swidth)</option>
|
onchange=":field.getOnChange(ztool, 'search', className)">
|
||||||
</select>
|
<option for="tied in objects" value=":tied.uid" selected=":selectAll"
|
||||||
</x>''')
|
var2="title=field.getReferenceLabel(tied, unlimited=True)"
|
||||||
|
title=":title">:ztool.truncateValue(title, field.swidth)</option>
|
||||||
|
</select>''')
|
||||||
|
|
||||||
def __init__(self, klass=None, attribute=None, validator=None,
|
def __init__(self, klass=None, attribute=None, validator=None,
|
||||||
multiplicity=(0,1), default=None, add=False, addConfirm=False,
|
multiplicity=(0,1), default=None, add=False, addConfirm=False,
|
||||||
|
@ -740,11 +741,12 @@ class Ref(Field):
|
||||||
newIndex = oldIndex + move
|
newIndex = oldIndex + move
|
||||||
uids.insert(newIndex, uid)
|
uids.insert(newIndex, uid)
|
||||||
|
|
||||||
def getSelectableObjects(self, obj):
|
def getPossibleValues(self, obj):
|
||||||
'''This method returns the list of all objects that can be selected to
|
'''This method returns the list of all objects that can be selected
|
||||||
be linked as references to p_obj via p_self. If master values are
|
to be linked as references to p_obj via p_self. It is applicable only
|
||||||
present in the request, we use field.masterValues method instead of
|
for ref fields with link=True. If master values are present in the
|
||||||
self.select.'''
|
request, we use field.masterValues method instead of self.select.
|
||||||
|
'''
|
||||||
req = obj.request
|
req = obj.request
|
||||||
if 'masterValues' in req:
|
if 'masterValues' in req:
|
||||||
# Convert masterValue(s) from UID(s) to real object(s).
|
# Convert masterValue(s) from UID(s) to real object(s).
|
||||||
|
@ -762,8 +764,8 @@ class Ref(Field):
|
||||||
else:
|
else:
|
||||||
# If this field is a ajax-updatable slave, no need to compute
|
# If this field is a ajax-updatable slave, no need to compute
|
||||||
# selectable objects: it will be overridden by method
|
# selectable objects: it will be overridden by method
|
||||||
# self.masterValue by a subsequent ajax request (=the "if" statement
|
# self.masterValue by a subsequent ajax request (=the "if"
|
||||||
# above).
|
# statement above).
|
||||||
if self.masterValue and callable(self.masterValue): return []
|
if self.masterValue and callable(self.masterValue): return []
|
||||||
if not self.select:
|
if not self.select:
|
||||||
# No select method has been defined: we must retrieve all
|
# No select method has been defined: we must retrieve all
|
||||||
|
@ -774,7 +776,7 @@ class Ref(Field):
|
||||||
return self.select(obj)
|
return self.select(obj)
|
||||||
|
|
||||||
xhtmlToText = re.compile('<.*?>', re.S)
|
xhtmlToText = re.compile('<.*?>', re.S)
|
||||||
def getReferenceLabel(self, refObject):
|
def getReferenceLabel(self, refObject, unlimited=False):
|
||||||
'''p_self must have link=True. I need to display, on an edit view, the
|
'''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
|
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
|
object(s) to link through the Ref. The information to display may
|
||||||
|
@ -793,6 +795,7 @@ class Ref(Field):
|
||||||
if res:
|
if res:
|
||||||
prefix = ' | '
|
prefix = ' | '
|
||||||
res += prefix + value
|
res += prefix + value
|
||||||
|
if unlimited: return res
|
||||||
maxWidth = self.width or 30
|
maxWidth = self.width or 30
|
||||||
if len(res) > maxWidth:
|
if len(res) > maxWidth:
|
||||||
res = res[:maxWidth-2] + '...'
|
res = res[:maxWidth-2] + '...'
|
||||||
|
|
|
@ -144,8 +144,7 @@ class String(Field):
|
||||||
<x if="not multipleValues">:field.pxView</x>
|
<x if="not multipleValues">:field.pxView</x>
|
||||||
</x>''')
|
</x>''')
|
||||||
|
|
||||||
pxSearch = Px('''<x>
|
pxSearch = Px('''
|
||||||
<label lfor="widgetName">:_(field.labelId)</label><br/>
|
|
||||||
<!-- Show a simple search field for most String fields -->
|
<!-- Show a simple search field for most String fields -->
|
||||||
<input if="not field.isSelect" type="text" maxlength=":field.maxChars"
|
<input if="not field.isSelect" type="text" maxlength=":field.maxChars"
|
||||||
size=":field.swidth" value=":field.sdefault"
|
size=":field.swidth" value=":field.sdefault"
|
||||||
|
@ -173,8 +172,7 @@ class String(Field):
|
||||||
selected=":v[0] in preSelected" value=":v[0]"
|
selected=":v[0] in preSelected" value=":v[0]"
|
||||||
title=":v[1]">:ztool.truncateValue(v[1], field.swidth)</option>
|
title=":v[1]">:ztool.truncateValue(v[1], field.swidth)</option>
|
||||||
</select>
|
</select>
|
||||||
</x><br/>
|
</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
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
# "edit" represents a given page for a given Appy class, in edit mode.
|
# "edit" represents a given page for a given Appy class, in edit mode.
|
||||||
# "cell" represents a cell in a table, like when we need to render a field
|
# "cell" represents a cell in a table, like when we need to render a field
|
||||||
# value in a query result or in a reference table.
|
# value in a query result or in a reference table.
|
||||||
|
# "search" represents an advanced search screen.
|
||||||
|
|
||||||
# Layout elements for a class or page ------------------------------------------
|
# Layout elements for a class or page ------------------------------------------
|
||||||
# s - The page summary, containing summarized information about the page or
|
# s - The page summary, containing summarized information about the page or
|
||||||
|
@ -113,7 +114,7 @@ class Table:
|
||||||
'''Represents a table where to dispose graphical elements.'''
|
'''Represents a table where to dispose graphical elements.'''
|
||||||
simpleParams = ('style', 'css_class', 'cellpadding', 'cellspacing', 'width',
|
simpleParams = ('style', 'css_class', 'cellpadding', 'cellspacing', 'width',
|
||||||
'align')
|
'align')
|
||||||
derivedRepls = {'view': 'hrvd', 'cell': 'ldc'}
|
derivedRepls = {'view': 'hrvd', 'search': '', 'cell': 'ldc'}
|
||||||
def __init__(self, layoutString=None, style=None, css_class='',
|
def __init__(self, layoutString=None, style=None, css_class='',
|
||||||
cellpadding=0, cellspacing=0, width='100%', align='left',
|
cellpadding=0, cellspacing=0, width='100%', align='left',
|
||||||
other=None, derivedType=None):
|
other=None, derivedType=None):
|
||||||
|
|
|
@ -648,6 +648,8 @@ class ToolMixin(BaseMixin):
|
||||||
for attrName in rq.form.keys():
|
for attrName in rq.form.keys():
|
||||||
if attrName.startswith('w_') and \
|
if attrName.startswith('w_') and \
|
||||||
not self._searchValueIsEmpty(attrName):
|
not self._searchValueIsEmpty(attrName):
|
||||||
|
field = self.getAppyType(attrName[2:], rq.form['className'])
|
||||||
|
if not field.persist: continue
|
||||||
# We have a(n interval of) value(s) that is not empty for a
|
# We have a(n interval of) value(s) that is not empty for a
|
||||||
# given field.
|
# given field.
|
||||||
attrValue = rq.form[attrName]
|
attrValue = rq.form[attrName]
|
||||||
|
@ -1384,18 +1386,6 @@ class ToolMixin(BaseMixin):
|
||||||
res = self.goto(siteUrl, self.translate('wrong_password_reinit'))
|
res = self.goto(siteUrl, self.translate('wrong_password_reinit'))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getSearchValues(self, name, className):
|
|
||||||
'''Gets the possible values for selecting a value for searching field
|
|
||||||
p_name belonging to class p_className.'''
|
|
||||||
klass = self.getAppyClass(className, wrapper=True)
|
|
||||||
method = getattr(klass, name).searchSelect
|
|
||||||
tool = self.appy()
|
|
||||||
if method.__class__.__name__ == 'function':
|
|
||||||
objects = method(tool)
|
|
||||||
else:
|
|
||||||
objects = method.__get__(tool)(tool)
|
|
||||||
return [(o.uid, o) for o in objects]
|
|
||||||
|
|
||||||
def getGoogleAnalyticsCode(self):
|
def getGoogleAnalyticsCode(self):
|
||||||
'''If the config defined a Google Analytics ID, this method returns the
|
'''If the config defined a Google Analytics ID, this method returns the
|
||||||
Javascript code to be included in every page, allowing Google
|
Javascript code to be included in every page, allowing Google
|
||||||
|
|
|
@ -690,6 +690,7 @@ class BaseMixin:
|
||||||
'''Returns the database value of field named p_name for p_self.
|
'''Returns the database value of field named p_name for p_self.
|
||||||
If p_onlyIfSync is True, it returns the value only if appyType can be
|
If p_onlyIfSync is True, it returns the value only if appyType can be
|
||||||
retrieved in synchronous mode.'''
|
retrieved in synchronous mode.'''
|
||||||
|
if layoutType == 'search': return # No object in search screens.
|
||||||
field = self.getAppyType(name)
|
field = self.getAppyType(name)
|
||||||
if not onlyIfSync or (onlyIfSync and field.sync[layoutType]):
|
if not onlyIfSync or (onlyIfSync and field.sync[layoutType]):
|
||||||
# We must really get the field value.
|
# We must really get the field value.
|
||||||
|
@ -699,11 +700,6 @@ class BaseMixin:
|
||||||
listType = self.getAppyType(listName)
|
listType = self.getAppyType(listName)
|
||||||
return listType.getInnerValue(self, outerValue, name, int(i))
|
return listType.getInnerValue(self, outerValue, name, int(i))
|
||||||
|
|
||||||
def getFormattedFieldValue(self, name, value, showChanges=False):
|
|
||||||
'''Gets a nice, string representation of p_value which is a value from
|
|
||||||
field named p_name.'''
|
|
||||||
return self.getAppyType(name).getFormattedValue(self,value,showChanges)
|
|
||||||
|
|
||||||
def getRequestFieldValue(self, name):
|
def getRequestFieldValue(self, name):
|
||||||
'''Gets the value of field p_name as may be present in the request.'''
|
'''Gets the value of field p_name as may be present in the request.'''
|
||||||
# Return the request value for standard fields.
|
# Return the request value for standard fields.
|
||||||
|
|
|
@ -10,7 +10,8 @@ from appy.gen.wrappers.TranslationWrapper import TranslationWrapper as WT
|
||||||
from appy.gen.wrappers.PageWrapper import PageWrapper as WPage
|
from appy.gen.wrappers.PageWrapper import PageWrapper as WPage
|
||||||
from Globals import InitializeClass
|
from Globals import InitializeClass
|
||||||
from AccessControl import ClassSecurityInfo
|
from AccessControl import ClassSecurityInfo
|
||||||
tfw = {"edit":"f","cell":"f","view":"f"} # Layout for Translation fields
|
# Layouts for Translation fields
|
||||||
|
tfw = {"edit":"f","cell":"f","view":"f","search":"f"}
|
||||||
<!imports!>
|
<!imports!>
|
||||||
|
|
||||||
<!User!>
|
<!User!>
|
||||||
|
|
|
@ -93,6 +93,7 @@ input.button { border-width: 0 !important; color: #666666; height: 23px;
|
||||||
margin: 0.1em 0 0.3em ; border-bottom: 1px dashed grey }
|
margin: 0.1em 0 0.3em ; border-bottom: 1px dashed grey }
|
||||||
.portletSearch { font-size: 90%; font-style: italic }
|
.portletSearch { font-size: 90%; font-style: italic }
|
||||||
.inputSearch { height: 15px; width: 132px; margin: 3px 3px 2px 3px !important }
|
.inputSearch { height: 15px; width: 132px; margin: 3px 3px 2px 3px !important }
|
||||||
|
td.search { padding-top: 8px }
|
||||||
.content { padding: 14px 14px 9px 15px; background-color: #f1f1f1 }
|
.content { padding: 14px 14px 9px 15px; background-color: #f1f1f1 }
|
||||||
.grey { display: none; position: absolute; left: 0px; top: 0px; z-index:2;
|
.grey { display: none; position: absolute; left: 0px; top: 0px; z-index:2;
|
||||||
background:grey; opacity:0.5; -moz-opacity:0.5; -khtml-opacity:0.5;
|
background:grey; opacity:0.5; -moz-opacity:0.5; -khtml-opacity:0.5;
|
||||||
|
|
|
@ -244,15 +244,16 @@ function askComputedField(hookId, objectUrl, fieldName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function askField(hookId, objectUrl, layoutType, showChanges, masterValues,
|
function askField(hookId, objectUrl, layoutType, showChanges, masterValues,
|
||||||
requestValue, error){
|
requestValue, error, className){
|
||||||
// Sends an Ajax request for getting the content of any field.
|
// Sends an Ajax request for getting the content of any field.
|
||||||
var fieldName = hookId.split('_')[1];
|
var fieldName = hookId.split('_')[1];
|
||||||
var params = {'layoutType': layoutType, 'showChanges': showChanges};
|
var params = {'layoutType': layoutType, 'showChanges': showChanges};
|
||||||
if (masterValues) params['masterValues'] = masterValues.join('*');
|
if (masterValues) params['masterValues'] = masterValues.join('*');
|
||||||
if (requestValue) params[fieldName] = requestValue;
|
if (requestValue) params[fieldName] = requestValue;
|
||||||
if (error) params[fieldName + '_error'] = error;
|
if (error) params[fieldName + '_error'] = error;
|
||||||
askAjaxChunk(hookId, 'GET', objectUrl, fieldName+':pxRender', params, null,
|
var px = fieldName + ':pxRender';
|
||||||
evalInnerScripts);
|
if (className) px = className + ':' + px;
|
||||||
|
askAjaxChunk(hookId, 'GET', objectUrl, px, params, null, evalInnerScripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function used by checkbox widgets for having radio-button-like behaviour
|
// Function used by checkbox widgets for having radio-button-like behaviour
|
||||||
|
@ -354,6 +355,8 @@ function getSlaves(master) {
|
||||||
allSlaves = getElementsHavingName('table', 'slave');
|
allSlaves = getElementsHavingName('table', 'slave');
|
||||||
res = [];
|
res = [];
|
||||||
masterName = master.attributes['name'].value;
|
masterName = master.attributes['name'].value;
|
||||||
|
// Remove leading 'w_' if the master is in a search screen.
|
||||||
|
if (masterName.indexOf('w_') == 0) masterName = masterName.slice(2);
|
||||||
if (master.type == 'checkbox') {
|
if (master.type == 'checkbox') {
|
||||||
masterName = masterName.substr(0, masterName.length-8);
|
masterName = masterName.substr(0, masterName.length-8);
|
||||||
}
|
}
|
||||||
|
@ -370,7 +373,8 @@ function getSlaves(master) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSlaves(master,slave,objectUrl,layoutType,requestValues,errors){
|
function updateSlaves(master, slave, objectUrl, layoutType, requestValues,
|
||||||
|
errors, className){
|
||||||
/* Given the value(s) in a master field, we must update slave's visibility or
|
/* Given the value(s) in a master field, we must update slave's visibility or
|
||||||
value(s). If p_slave is given, it updates only this slave. Else, it updates
|
value(s). If p_slave is given, it updates only this slave. Else, it updates
|
||||||
all slaves of p_master. */
|
all slaves of p_master. */
|
||||||
|
@ -401,7 +405,8 @@ function updateSlaves(master,slave,objectUrl,layoutType,requestValues,errors){
|
||||||
var err = null;
|
var err = null;
|
||||||
if (errors && (slaveName in errors))
|
if (errors && (slaveName in errors))
|
||||||
err = errors[slaveName];
|
err = errors[slaveName];
|
||||||
askField(slaveId,objectUrl,layoutType,false,masterValues,reqValue,err);
|
askField(slaveId, objectUrl, layoutType, false, masterValues, reqValue,
|
||||||
|
err, className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -495,6 +495,7 @@ class ToolWrapper(AbstractWrapper):
|
||||||
refInfo=req.get('ref', None);
|
refInfo=req.get('ref', None);
|
||||||
searchInfo=ztool.getSearchInfo(className, refInfo);
|
searchInfo=ztool.getSearchInfo(className, refInfo);
|
||||||
cssJs={};
|
cssJs={};
|
||||||
|
layoutType='search';
|
||||||
x=ztool.getCssJs(searchInfo.fields, 'edit', cssJs)">
|
x=ztool.getCssJs(searchInfo.fields, 'edit', cssJs)">
|
||||||
|
|
||||||
<!-- Include type-specific CSS and JS. -->
|
<!-- Include type-specific CSS and JS. -->
|
||||||
|
@ -506,7 +507,6 @@ class ToolWrapper(AbstractWrapper):
|
||||||
<!-- Search title -->
|
<!-- Search title -->
|
||||||
<h1><x>:_('%s_plural'%className)</x> –
|
<h1><x>:_('%s_plural'%className)</x> –
|
||||||
<x>:_('search_title')</x></h1>
|
<x>:_('search_title')</x></h1>
|
||||||
<br/>
|
|
||||||
<!-- Form for searching objects of request/className. -->
|
<!-- Form for searching objects of request/className. -->
|
||||||
<form name="search" action=":ztool.absolute_url()+'/do'" method="post">
|
<form name="search" action=":ztool.absolute_url()+'/do'" method="post">
|
||||||
<input type="hidden" name="action" value="SearchObjects"/>
|
<input type="hidden" name="action" value="SearchObjects"/>
|
||||||
|
@ -516,13 +516,11 @@ class ToolWrapper(AbstractWrapper):
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
<tr for="searchRow in ztool.getGroupedSearchFields(searchInfo)"
|
<tr for="searchRow in ztool.getGroupedSearchFields(searchInfo)"
|
||||||
valign="top">
|
valign="top">
|
||||||
<td for="field in searchRow"
|
<td for="field in searchRow" class="search"
|
||||||
var2="scolspan=field and field.scolspan or 1"
|
var2="scolspan=field and field.scolspan or 1"
|
||||||
colspan=":scolspan"
|
colspan=":scolspan"
|
||||||
width=":'%d%%' % ((100/searchInfo.nbOfColumns)*scolspan)">
|
width=":'%d%%' % ((100/searchInfo.nbOfColumns)*scolspan)">
|
||||||
<x if="field"
|
<x if="field">:field.pxRender</x>
|
||||||
var2="name=field.name;
|
|
||||||
widgetName='w_%s' % name">:field.pxSearch</x>
|
|
||||||
<br class="discreet"/>
|
<br class="discreet"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -575,7 +575,9 @@ class AbstractWrapper(object):
|
||||||
lang=ztool.getUserLanguage(); q=ztool.quote;
|
lang=ztool.getUserLanguage(); q=ztool.quote;
|
||||||
action=req.get('action', None);
|
action=req.get('action', None);
|
||||||
px=req['px'].split(':');
|
px=req['px'].split(':');
|
||||||
field=(len(px) == 2) and zobj.getAppyType(px[0]) or None;
|
className=(len(px) == 3) and px[0] or None;
|
||||||
|
field=className and zobj.getAppyType(px[1], className) or None;
|
||||||
|
field=(len(px) == 2) and zobj.getAppyType(px[0]) or field;
|
||||||
dir=ztool.getLanguageDirection(lang);
|
dir=ztool.getLanguageDirection(lang);
|
||||||
dleft=(dir == 'ltr') and 'left' or 'right';
|
dleft=(dir == 'ltr') and 'left' or 'right';
|
||||||
dright=(dir == 'ltr') and 'right' or 'left';
|
dright=(dir == 'ltr') and 'right' or 'left';
|
||||||
|
@ -590,7 +592,7 @@ class AbstractWrapper(object):
|
||||||
|
|
||||||
<!-- Then, call the PX on p_obj or on p_field. -->
|
<!-- Then, call the PX on p_obj or on p_field. -->
|
||||||
<x if="not field">:getattr(obj, px[0])</x>
|
<x if="not field">:getattr(obj, px[0])</x>
|
||||||
<x if="field">:getattr(field, px[1])</x>
|
<x if="field">:getattr(field, px[-1])</x>
|
||||||
</x>''')
|
</x>''')
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue