[gen] Bugfixes.
This commit is contained in:
parent
f842c0ce02
commit
8b90d877a8
|
@ -12,14 +12,15 @@ class Calendar(Field):
|
|||
'''This field allows to produce an agenda (monthly view) and view/edit
|
||||
events on it.'''
|
||||
jsFiles = {'view': ('calendar.js',)}
|
||||
DateTime = DateTime
|
||||
|
||||
# Month view for a calendar. Called by pxView, and directly from the UI,
|
||||
# via Ajax, when the user selects another month.
|
||||
pxMonthView = Px('''
|
||||
pxViewMonth = Px('''
|
||||
<div var="ajaxHookId=zobj.id + field.name;
|
||||
month=req['month'];
|
||||
monthDayOne=DateTime('%s/01' % month);
|
||||
today=DateTime('00:00');
|
||||
monthDayOne=field.DateTime('%s/01' % month);
|
||||
today=field.DateTime('00:00');
|
||||
grid=field.getMonthGrid(month);
|
||||
allEventTypes=field.getEventTypes(zobj);
|
||||
preComputed=field.getPreComputedInfo(zobj, monthDayOne, grid);
|
||||
|
@ -34,7 +35,7 @@ class Calendar(Field):
|
|||
otherCalendars=field.getOtherCalendars(zobj, preComputed)"
|
||||
id=":ajaxHookId">
|
||||
|
||||
<script type="text/javascript">:'var %s_maxEventLength = %d' % \
|
||||
<script>:'var %s_maxEventLength = %d;' % \
|
||||
(field.name, field.maxEventLength)</script>
|
||||
|
||||
<!-- Month chooser -->
|
||||
|
@ -90,14 +91,12 @@ class Calendar(Field):
|
|||
mayCreate=mayEdit and not events;
|
||||
mayDelete=mayEdit and events;
|
||||
day=date.day();
|
||||
dayString=date.strftime('%Y/%m/%d')"
|
||||
style="date.isCurrentDay() and 'font-weight:bold' or \
|
||||
dayString=date.strftime('%Y/%m/%d');
|
||||
js=mayEdit and 'toggleVisibility(this, %s)' % q('img') \
|
||||
or ''"
|
||||
style=":date.isCurrentDay() and 'font-weight:bold' or \
|
||||
'font-weight:normal'"
|
||||
class=":cssClasses"
|
||||
onmouseover=":mayEdit and 'this.getElementsByTagName(\
|
||||
%s)[0].style.visibility=%s' % (q('img'), q('visible')) or ''"
|
||||
onmouseout="mayEdit and 'this.getElementsByTagName(\
|
||||
%s)[0].style.visibility=%s' % (q('img'), q('hidden')) or ''">
|
||||
class=":cssClasses" onmouseover=":js" onmouseout=":js">
|
||||
<span>:day</span>
|
||||
<span if="day == 1">:_('month_%s_short' % date.aMonth())</span>
|
||||
<!-- Icon for adding an event -->
|
||||
|
@ -138,11 +137,11 @@ class Calendar(Field):
|
|||
<div var="prefix='%s_newEvent' % field.name;
|
||||
popupId=prefix + 'Popup'"
|
||||
id=":popupId" class="popup" align="center">
|
||||
<form id="prefix + 'Form'" method="post">
|
||||
<form id=":prefix + 'Form'" method="post">
|
||||
<input type="hidden" name="fieldName" value=":field.name"/>
|
||||
<input type="hidden" name="month" value=":month"/>
|
||||
<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="day"/>
|
||||
|
||||
|
@ -177,11 +176,11 @@ class Calendar(Field):
|
|||
<input type="hidden" name="fieldName" value=":field.name"/>
|
||||
<input type="hidden" name="month" value=":month"/>
|
||||
<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="day"/>
|
||||
|
||||
<div align="center" style="margin-bottom: 5px">_('action_confirm')</div>
|
||||
<div align="center"
|
||||
style="margin-bottom: 5px">:_('action_confirm')</div>
|
||||
|
||||
<!-- Delete successive events ? -->
|
||||
<div class="discreet" style="margin-bottom: 10px"
|
||||
|
@ -205,7 +204,7 @@ class Calendar(Field):
|
|||
pxView = pxCell = Px('''
|
||||
<x var="defaultDate=field.getDefaultDate(zobj);
|
||||
x=req.set('month', defaultDate.strftime('%Y/%m'));
|
||||
x=req.set('fieldName', field.name)">:field.pxMonthView</x>''')
|
||||
x=req.set('fieldName', field.name)">:field.pxViewMonth</x>''')
|
||||
|
||||
pxEdit = pxSearch = ''
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ class UiGroup:
|
|||
</tr>
|
||||
<!-- The rows of widgets -->
|
||||
<tr valign=":field.valign" for="row in field.elements">
|
||||
<td for="field in row" colspan=":field.colspan"
|
||||
<td for="field in row" colspan=":field.colspan|1"
|
||||
style=":not loop.field.last and ('padding-right:%s'% cellgap) or ''">
|
||||
<x if="field">
|
||||
<x if="field.type == 'group'">:field.pxView</x>
|
||||
|
|
|
@ -51,6 +51,9 @@ class Pod(Field):
|
|||
# "r"ight "m"ulti-template (where the global field label is not used
|
||||
rmLayouts = {'view': Table('f!', css_class='podTable')}
|
||||
allFormats = {'.odt': ('pdf', 'doc', 'odt'), '.ods': ('xls', 'ods')}
|
||||
# Parameters needed to perform a query for query-related pods
|
||||
queryParams = ('className', 'search', 'sortKey', 'sortOrder',
|
||||
'filterKey', 'filterValue')
|
||||
|
||||
POD_ERROR = 'An error occurred while generating the document. Please ' \
|
||||
'contact the system administrator.'
|
||||
|
@ -67,7 +70,8 @@ class Pod(Field):
|
|||
src=":url(fmt + iconSuffix)" class="clickable"
|
||||
title=":field.getIconTitle(obj, fmt, frozen)"
|
||||
onclick=":'generatePod(this,%s,%s,%s,%s,%s,null,%s)' % (q(uid), \
|
||||
q(name), q(info.template), q(fmt), q(ztool.getQueryInfo()), gc)"/>''')
|
||||
q(name), q(info.template), q(fmt), q(field.getQueryInfo(req)), \
|
||||
gc)"/>''')
|
||||
|
||||
pxView = pxCell = Px('''
|
||||
<x var="uid=obj.uid;
|
||||
|
@ -127,7 +131,7 @@ class Pod(Field):
|
|||
<td colspan="2">
|
||||
<a var="js='generatePod(this,%s,%s,%s,%s,%s,null,%s,%s)' % \
|
||||
(q(uid), q(name), q(info.template), q(fmt), \
|
||||
q(ztool.getQueryInfo()), gc, q(mailing))"
|
||||
q(field.getQueryInfo(req)), gc, q(mailing))"
|
||||
onclick=":'askConfirm(%s,%s)' % (q('script'), q(js, False))"
|
||||
title=":sendLabel">
|
||||
<img src=":url('email')" align="left" style="margin-right: 2px"/>
|
||||
|
@ -538,7 +542,7 @@ class Pod(Field):
|
|||
# result in the pod context.
|
||||
if queryData:
|
||||
# Retrieve query params
|
||||
cmd = ', '.join(tool.o.queryParamNames)
|
||||
cmd = ', '.join(Pod.queryParams)
|
||||
cmd += " = queryData.split(';')"
|
||||
exec cmd
|
||||
# (re-)execute the query, but without any limit on the number of
|
||||
|
@ -734,6 +738,13 @@ class Pod(Field):
|
|||
setattr(res['_checked'], self.getChecked, objects)
|
||||
return res
|
||||
|
||||
def getQueryInfo(self, req):
|
||||
'''This method encodes in a string all the params in the request that
|
||||
are required for re-triggering a search.'''
|
||||
if not req.has_key('search'): return ''
|
||||
return ';'.join([req.get(key,'').replace(';','') \
|
||||
for key in Pod.queryParams])
|
||||
|
||||
def onUiRequest(self, obj, rq):
|
||||
'''This method is called when an action tied to this pod field
|
||||
(generate, freeze, upload...) is triggered from the user
|
||||
|
|
|
@ -1270,17 +1270,15 @@ class Ref(Field):
|
|||
px = (params['scope'] == 'poss') and 'pxViewPickList' or 'pxView'
|
||||
px = '%s:%s' % (self.name, px)
|
||||
params = sutils.getStringDict(params)
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', " \
|
||||
"'%s', %s, null, '%s')" % \
|
||||
(hook, hook, px, params, zobj.absolute_url())
|
||||
return "new AjaxData('%s', '%s', %s, null, '%s')" % \
|
||||
(hook, px, params, zobj.absolute_url())
|
||||
|
||||
def getAjaxDataRow(self, obj, parentHook, **params):
|
||||
'''Initializes an AjaxData object on the DOM node corresponding to
|
||||
p_hook = a row within the list of referred objects.'''
|
||||
hook = obj.id
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', " \
|
||||
"'pxViewAsTiedFromAjax',%s,'%s','%s')" % \
|
||||
(hook, hook, sutils.getStringDict(params), parentHook, obj.url)
|
||||
return "new AjaxData('%s', 'pxViewAsTiedFromAjax', %s, '%s', '%s')" % \
|
||||
(hook, sutils.getStringDict(params), parentHook, obj.url)
|
||||
|
||||
def doChangeOrder(self, obj):
|
||||
'''Moves a referred object up/down/top/bottom.'''
|
||||
|
|
|
@ -278,8 +278,7 @@ class UiSearch:
|
|||
target=ztool.getLinksTargetInfo(klass)"
|
||||
id=":ajaxHookId">
|
||||
|
||||
<x if="zobjects or filterValue">
|
||||
<!-- Display here POD templates if required -->
|
||||
<x if="zobjects or filterValue"> <!-- Pod templates -->
|
||||
<table var="fields=ztool.getResultPodFields(className);
|
||||
layoutType='view'"
|
||||
if="not inPopup and zobjects and fields" align=":dright">
|
||||
|
@ -404,22 +403,21 @@ class UiSearch:
|
|||
# not needed because included in the PX name. But they are requested by
|
||||
# sub-Ajax queries at the row level.
|
||||
params['className'] = self.className
|
||||
params['searchName'] = self.name
|
||||
params['searchName'] = params['search'] = self.name
|
||||
req = ztool.REQUEST
|
||||
for param, default in UiSearch.sortFilterDefaults.iteritems():
|
||||
params[param] = req.get(param, default)
|
||||
# Convert params into a JS dict
|
||||
params = sutils.getStringDict(params)
|
||||
px = '%s:%s:pxResult' % (self.className, self.name)
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', '%s', %s, " \
|
||||
"null, '%s')" % (hook, hook, px, params, ztool.absolute_url())
|
||||
return "new AjaxData('%s', '%s', %s, null, '%s')" % \
|
||||
(hook, px, params, ztool.absolute_url())
|
||||
|
||||
def getAjaxDataRow(self, zobj, parentHook, **params):
|
||||
'''Initializes an AjaxData object on the DOM node corresponding to
|
||||
p_hook = a row within the list of results.'''
|
||||
hook = zobj.id
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', " \
|
||||
"'pxViewAsResultFromAjax',%s,'%s','%s')" % \
|
||||
(hook, hook, sutils.getStringDict(params), parentHook,
|
||||
return "new AjaxData('%s', 'pxViewAsResultFromAjax', %s, '%s', '%s')"% \
|
||||
(hook, sutils.getStringDict(params), parentHook,
|
||||
zobj.absolute_url())
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -435,11 +435,12 @@ class String(Field):
|
|||
# Default width, height and maxChars vary according to String format
|
||||
if width == None:
|
||||
if format == String.TEXT: self.width = 60
|
||||
# This width corresponds to the standard width of an Appy page.
|
||||
if format == String.XHTML: self.width = None
|
||||
# This width corresponds to the standard width of an Appy page
|
||||
elif format == String.XHTML: self.width = None
|
||||
else: self.width = 30
|
||||
if height == None:
|
||||
if format == String.TEXT: self.height = 5
|
||||
elif format == String.XHTML: self.height = None
|
||||
elif self.isSelect: self.height = 4
|
||||
else: self.height = 1
|
||||
if maxChars == None:
|
||||
|
@ -987,6 +988,7 @@ class String(Field):
|
|||
'format_tags': ';'.join(self.styles),
|
||||
'scayt_sLang': self.getCkLanguage(obj, language)}
|
||||
if self.width: ckAttrs['width'] = self.width
|
||||
if self.height: ckAttrs['height'] = self.height
|
||||
if self.spellcheck: ckAttrs['scayt_autoStartup'] = True
|
||||
if self.allowImageUpload:
|
||||
ckAttrs['filebrowserUploadUrl'] = '%s/upload' % obj.absolute_url()
|
||||
|
|
|
@ -73,7 +73,9 @@ class Config:
|
|||
# of classes defined in your application.
|
||||
defaultCreators = ['Manager']
|
||||
# The "root" classes are those that will get their menu in the user
|
||||
# interface. Put their names in the list below.
|
||||
# interface. Put their names in the list below. If you leave the list empty,
|
||||
# all gen-classes will be considered root classes (the default). If
|
||||
# rootClasses is None, no class will be considered as root.
|
||||
rootClasses = []
|
||||
# Number of translations for every page on a Translation object
|
||||
translationsPerPage = 30
|
||||
|
|
|
@ -226,6 +226,7 @@ class ToolMixin(BaseMixin):
|
|||
'''Returns the list of root classes for this application'''
|
||||
cfg = self.getProductConfig().appConfig
|
||||
rootClasses = cfg.rootClasses
|
||||
if rootClasses == None: return [] # No root class at all
|
||||
if not rootClasses:
|
||||
# We consider every class as being a root class
|
||||
rootClasses = self.getProductConfig().appClassNames
|
||||
|
@ -259,19 +260,6 @@ class ToolMixin(BaseMixin):
|
|||
fields.append(field)
|
||||
return Object(fields=fields, nbOfColumns=nbOfColumns)
|
||||
|
||||
queryParamNames = ('className', 'search', 'sortKey', 'sortOrder',
|
||||
'filterKey', 'filterValue')
|
||||
def getQueryInfo(self):
|
||||
'''If we are showing search results, this method encodes in a string all
|
||||
the params in the request that are required for re-triggering the
|
||||
search.'''
|
||||
rq = self.REQUEST
|
||||
res = ''
|
||||
if rq.has_key('search'):
|
||||
res = ';'.join([rq.get(key,'').replace(';','') \
|
||||
for key in self.queryParamNames])
|
||||
return res
|
||||
|
||||
def showPortlet(self, obj, layoutType):
|
||||
'''When must the portlet be shown? p_obj and p_layoutType can be None
|
||||
if we are not browing any objet (ie, we are on the home page).'''
|
||||
|
|
|
@ -246,6 +246,8 @@ function AjaxData(hook, px, params, parentHook, url, mode, beforeSend, onGet) {
|
|||
/* If a parentHook is spefified, this AjaxData must be completed with a parent
|
||||
AjaxData instance. */
|
||||
this.parentHook = parentHook;
|
||||
// Inject this AjaxData instance into p_hook
|
||||
getAjaxHook(hook, true)['ajax'] = this;
|
||||
}
|
||||
|
||||
function askAjax(hook, form, params) {
|
||||
|
@ -269,6 +271,12 @@ function askAjax(hook, form, params) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Resolve dynamic parameter "cbChecked" if present
|
||||
if ('cbChecked' in d.params) {
|
||||
var cb = getAjaxHook(d.params['cbChecked'], true);
|
||||
if (cb) d.params['cbChecked'] = cb.checked;
|
||||
else delete d.params['cbChecked'];
|
||||
}
|
||||
// If a p_form id is given, integrate the form submission in the ajax request
|
||||
if (form) {
|
||||
var f = document.getElementById(form);
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
function toggleVisibility(node, nodeType){
|
||||
// Toggle visibility of all elements having p_nodeType within p_node
|
||||
var elements = node.getElementsByTagName(nodeType);
|
||||
for (var i=0; i<elements.length; i++){
|
||||
var sNode = elements[i];
|
||||
if (sNode.style.visibility == 'hidden') sNode.style.visibility = 'visible';
|
||||
else sNode.style.visibility = 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
function askMonthView(hookId, objectUrl, fieldName, month) {
|
||||
// Sends an Ajax request for getting the view month of a calendar field
|
||||
var params = {'month': month};
|
||||
askAjaxChunk(hookId, 'GET', objectUrl, fieldName+':pxMonthView', params);
|
||||
askAjaxChunk(hookId, 'GET', objectUrl, fieldName+':pxViewMonth', params);
|
||||
}
|
||||
|
||||
function openEventPopup(action, fieldName, day, spansDays,
|
||||
|
@ -78,7 +88,7 @@ function triggerCalendarEvent(action, hookId, fieldName, objectUrl,
|
|||
}
|
||||
var elems = f.elements;
|
||||
var params = {};
|
||||
// Put form elements into "params".
|
||||
// Put form elements into "params"
|
||||
for (var i=0; i < elems.length; i++) {
|
||||
params[elems[i].name] = elems[i].value;
|
||||
}
|
||||
|
|
|
@ -121,8 +121,8 @@ class UserWrapper(AbstractWrapper):
|
|||
zopeUser = self.getZopeUser()
|
||||
tool = self.tool.o
|
||||
zopeUser.__ = self.encryptPassword(newPassword)
|
||||
req = tool.REQUEST
|
||||
if hasattr(req, 'user') and (req.userLogin == login):
|
||||
req = getattr(tool, 'REQUEST', None)
|
||||
if req and hasattr(req, 'user') and (req.userLogin == login):
|
||||
# The user for which we change the password is the currently logged
|
||||
# user. So update the authentication cookie, too.
|
||||
gutils.writeCookie(login, newPassword, self.request)
|
||||
|
|
|
@ -575,18 +575,20 @@ class AbstractWrapper(object):
|
|||
<tr valign="top" class=":rowCss"
|
||||
var2="tiedUid=tied.o.id;
|
||||
objectIndex=field.getIndexOf(zobj, tiedUid)|None;
|
||||
mayView=tied.o.mayView()"
|
||||
mayView=tied.o.mayView();
|
||||
cbId='%s_%s' % (ajaxHookId, currentNumber)"
|
||||
id=":tiedUid">
|
||||
<td if="not inPickList and numbered">:field.pxNumber</td>
|
||||
<td if="checkboxes" class="cbCell">
|
||||
<input if="mayView" type="checkbox" name=":ajaxHookId" checked="checked"
|
||||
<input if="mayView" type="checkbox" name=":ajaxHookId" id=":cbId"
|
||||
var2="checked=cbChecked|True" checked=":checked"
|
||||
value=":tiedUid" onclick="toggleCb(this)"/>
|
||||
</td>
|
||||
<td for="column in columns" width=":column.width" align=":column.align"
|
||||
var2="refField=column.field">:refField.pxRenderAsTied</td>
|
||||
<!-- Store data in this tr node allowing to ajax-refresh it -->
|
||||
<script>:field.getAjaxDataRow(tied, ajaxHookId, rowCss=rowCss, \
|
||||
currentNumber=currentNumber)</script>
|
||||
currentNumber=currentNumber, cbChecked=cbId)</script>
|
||||
</tr>''')
|
||||
|
||||
# When calling pxViewAsTied from Ajax, this surrounding PX is called to
|
||||
|
@ -624,18 +626,18 @@ class AbstractWrapper(object):
|
|||
cbId='%s_%s' % (checkboxesId, currentNumber)"
|
||||
id=":zobj.id" class=":rowCss" valign="top">
|
||||
<!-- A checkbox if required -->
|
||||
<td if="checkboxes" class="cbCell" id=":cbId"
|
||||
style=":'display:%s' % cbDisplay">
|
||||
<td if="checkboxes" class="cbCell" style=":'display:%s' % cbDisplay">
|
||||
<input type="checkbox" name=":checkboxesId" checked="checked"
|
||||
value=":zobj.id" onclick="toggleCb(this)"/>
|
||||
var2="checked=cbChecked|True" value=":zobj.id"
|
||||
onclick="toggleCb(this)" id=":cbId"/>
|
||||
</td>
|
||||
<td for="column in columns"
|
||||
var2="field=column.field" id=":'field_%s' % field.name"
|
||||
width=":column.width"
|
||||
align=":column.align">:field.pxRenderAsResult</td>
|
||||
<!-- Store data in this tr node allowing to ajax-refresh it -->
|
||||
<script>:uiSearch.getAjaxDataRow(zobj, ajaxHookId, \
|
||||
currentNumber=currentNumber, rowCss=rowCss)</script>
|
||||
<script>:uiSearch.getAjaxDataRow(zobj, ajaxHookId, rowCss=rowCss, \
|
||||
currentNumber=currentNumber, cbChecked=cbId)</script>
|
||||
</tr>''')
|
||||
|
||||
# When calling pxViewAsResult from Ajax, this surrounding PX is called to
|
||||
|
@ -1291,7 +1293,7 @@ class AbstractWrapper(object):
|
|||
i -= 1
|
||||
|
||||
def removeEvent(self, event):
|
||||
'''Removes p_event from this object's history.'''
|
||||
'''Removes p_event from this object's history'''
|
||||
res = []
|
||||
# Because data change events carry the workflow state, we must ensure
|
||||
# that, after having removed p_event, this workflow state is still
|
||||
|
@ -1313,7 +1315,7 @@ class AbstractWrapper(object):
|
|||
return self.o.formatText(text, format)
|
||||
|
||||
def listStates(self):
|
||||
'''Lists the possible states for this object.'''
|
||||
'''Lists the possible states for this object'''
|
||||
res = []
|
||||
o = self.o
|
||||
workflow = o.getWorkflow()
|
||||
|
@ -1325,7 +1327,7 @@ class AbstractWrapper(object):
|
|||
return res
|
||||
|
||||
def path(self, name):
|
||||
'''Returns the absolute file name of file stored in File field p_nnamed
|
||||
'''Returns the absolute file name of file stored in File field p_named
|
||||
p_name.'''
|
||||
v = getattr(self, name)
|
||||
if v: return v.getFilePath(self)
|
||||
|
@ -1337,7 +1339,7 @@ class AbstractWrapper(object):
|
|||
return o.getAppyType(name).getIndexOf(o, obj.uid)
|
||||
|
||||
def allows(self, permission, raiseError=False):
|
||||
'''Check doc @Mixin.allows.'''
|
||||
'''Check doc @Mixin.allows'''
|
||||
return self.o.allows(permission, raiseError=raiseError)
|
||||
|
||||
def resetLocalRoles(self):
|
||||
|
|
Loading…
Reference in a new issue