[gen] Goodbye Zope Page Templates.

This commit is contained in:
Gaetan Delannay 2013-08-21 22:25:27 +02:00
parent 1bd77d68c4
commit 04852360fa
46 changed files with 102 additions and 3173 deletions

View file

@ -421,10 +421,6 @@ class Field:
self.hasLabel = self.hasLayoutElement('l', layouts)
self.hasDescr = self.hasLayoutElement('d', layouts)
self.hasHelp = self.hasLayoutElement('h', layouts)
# Store Table instance's dicts instead of instances: this way, they can
# be manipulated in ZPTs.
for layoutType in layouts.iterkeys():
layouts[layoutType] = layouts[layoutType].get()
return layouts
def hasLayoutElement(self, element, layouts):
@ -444,7 +440,7 @@ class Field:
value for the Field constructor.'''
res = '{'
for k, v in self.layouts.iteritems():
res += '"%s":"%s",' % (k, v['layoutString'])
res += '"%s":"%s",' % (k, v.layoutString)
res += '}'
return res

View file

@ -11,13 +11,12 @@ from persistent.list import PersistentList
class Calendar(Field):
'''This field allows to produce an agenda (monthly view) and view/edit
events on it.'''
jsFiles = {'view': ('widgets/calendar.js',)}
jsFiles = {'view': ('calendar.js',)}
# Month view for a calendar. Called by pxView, and directly from the UI,
# via Ajax, when the user selects another month.
pxMonthView = Px('''
<div var="field=zobj.getAppyType(req['fieldName']);
ajaxHookId=zobj.UID() + field.name;
<div var="ajaxHookId=zobj.UID() + field.name;
month=req['month'];
monthDayOne=DateTime('%s/01' % month);
today=DateTime('00:00');
@ -28,7 +27,7 @@ class Calendar(Field):
defaultDateMonth=defaultDate.strftime('%Y/%m');
previousMonth=field.getSiblingMonth(month, 'previous');
nextMonth=field.getSiblingMonth(month, 'next');
mayEdit=zobj.allows(widget['writePermission']);
mayEdit=zobj.allows(field.writePermission);
objUrl=zobj.absolute_url();
startDate=field.getStartDate(zobj);
endDate=field.getEndDate(zobj);
@ -106,10 +105,10 @@ class Calendar(Field):
<img class="clickable" style="visibility:hidden"
var="info=field.getApplicableEventsTypesAt(zobj, date, \
allEventTypes, preComputed, True)"
if="info['eventTypes']" src=":url('plus')"
if="info.eventTypes" src=":url('plus')"
onclick=":'openEventPopup(%s, %s, %s, null, %s, %s)' % \
(q('new'), q(field.name), q(dayString), q(info['eventTypes']),\
q(info['message']))"/>
(q('new'), q(field.name), q(dayString), q(info.eventTypes),\
q(info.message))"/>
</x>
<!-- Icon for deleting an event -->
<img if="mayDelete" class="clickable" style="visibility:hidden"
@ -117,15 +116,15 @@ class Calendar(Field):
onclick=":'openEventPopup(%s, %s, %s, %s, null, null)' % \
(q('del'), q(field.name), q(dayString), q(spansDays))"/>
<!-- A single event is allowed for the moment -->
<div if="events" var2="eventType=events[0]['eventType']">
<div if="events" var2="eventType=events[0].eventType">
<span style="color: grey">:field.getEventName(zobj, eventType)</span>
</div>
<!-- Events from other calendars -->
<x if="otherCalendars"
var2="otherEvents=field.getOtherEventsAt(zobj, date, \
otherCalendars)">
<div style=":'color: %s; font-style: italic' % event['color']"
for="event in otherEvents">:event['name']</div>
<div style=":'color: %s; font-style: italic' % event.color"
for="event in otherEvents">:event.name</div>
</x>
<!-- Additional info -->
<x var="info=field.getAdditionalInfoAt(zobj, date, preComputed)"
@ -409,7 +408,7 @@ class Calendar(Field):
return res.__dict__
return res
def getEventsAt(self, obj, date, asDict=True):
def getEventsAt(self, obj, date):
'''Returns the list of events that exist at some p_date (=day).'''
obj = obj.o # Ensure p_obj is not a wrapper.
if not hasattr(obj.aq_base, self.name): return
@ -422,16 +421,12 @@ class Calendar(Field):
days = months[month]
day = date.day()
if day not in days: return
if asDict:
res = [e.__dict__ for e in days[day]]
else:
res = days[day]
return res
return days[day]
def getEventTypeAt(self, obj, date):
'''Returns the event type of the first event defined at p_day, or None
if unspecified.'''
events = self.getEventsAt(obj, date, asDict=False)
events = self.getEventsAt(obj, date)
if not events: return
return events[0].eventType
@ -522,20 +517,20 @@ class Calendar(Field):
'''Returns True if, at p_date, an event is found of the same type as
p_otherEvents.'''
if not otherEvents: return False
events = self.getEventsAt(obj, date, asDict=False)
events = self.getEventsAt(obj, date)
if not events: return False
return events[0].eventType == otherEvents[0]['eventType']
return events[0].eventType == otherEvents[0].eventType
def getOtherEventsAt(self, obj, date, otherCalendars):
'''Gets events that are defined in p_otherCalendars at some p_date.'''
res = []
for o, field, color in otherCalendars:
events = field.getEventsAt(o.o, date, asDict=False)
events = field.getEventsAt(o.o, date)
if events:
eventType = events[0].eventType
eventName = field.getEventName(o.o, eventType)
info = Object(name=eventName, color=color)
res.append(info.__dict__)
res.append(info)
return res
def getEventName(self, obj, eventType):

View file

@ -85,7 +85,6 @@ class List(Field):
# Tuples of (names, Field instances) determining the format of every
# element in the list.
self.fields = fields
self.fieldsd = [(n, f.__dict__) for (n,f) in self.fields]
# Force some layouting for sub-fields, if subLayouts are given. So the
# one who wants freedom on tuning layouts at the field level must
# specify subLayouts=None.

View file

@ -158,7 +158,7 @@ class Pod(Field):
objs = tool.o.executeQuery(obj.o.portal_type, searchName=search,
sortBy=sortKey, sortOrder=sortOrder, filterKey=filterKey,
filterValue=filterValue, maxResults='NO_LIMIT')
podContext['objects'] = [o.appy() for o in objs['objects']]
podContext['objects'] = [o.appy() for o in objs.objects]
# Add the field-specific context if present.
if specificContext:
podContext.update(specificContext)

View file

@ -198,7 +198,7 @@ class Ref(Field):
<td>
<!-- Show forward or backward reference(s) -->
<table class=":not innerRef and 'list' or ''"
width=":innerRef and '100%' or field.layouts['view']['width']"
width=":innerRef and '100%' or field.layouts['view'].width"
var="columns=ztool.getColumnsSpecifiers(tiedClassName, \
field.shownInfo, dir)">
<tr if="field.showHeaders">
@ -318,10 +318,8 @@ class Ref(Field):
self.isBack = False
# Initialise the backward reference
self.back = back
self.backd = back.__dict__
back.isBack = True
back.back = self
back.backd = self.__dict__
# klass may be None in the case we are defining an auto-Ref to the
# same class as the class where this field is defined. In this case,
# when defining the field within the class, write
@ -580,7 +578,7 @@ class Ref(Field):
def mayAdd(self, obj):
'''May the user create a new referred object from p_obj via this Ref?'''
# We can't (yet) do that on back references.
if self.isBack: return No('is_back')
if self.isBack: return gutils.No('is_back')
# Check if this Ref is addable
if callable(self.add):
add = self.callMethod(obj, self.add)

View file

@ -147,9 +147,9 @@ class UiSearch:
pxView = Px('''
<div class="portletSearch">
<a href=":'%s?className=%s&amp;search=%s' % \
(queryUrl, rootClass, search['name'])"
class=":search['name'] == currentSearch and 'portletCurrent' or ''"
title=":search['translatedDescr']">:search['translated']</a>
(queryUrl, rootClass, search.name)"
class=":search.name == currentSearch and 'portletCurrent' or ''"
title=":search.translatedDescr">:search.translated</a>
</div>''')
def __init__(self, search, className, tool):

View file

@ -19,7 +19,7 @@ homePage = '<tal:h define="dummy python: request.RESPONSE.redirect(' \
# Stuff for tracking user activity ---------------------------------------------
loggedUsers = {}
originalTraverse = None
doNotTrack = ('.jpg','.gif','.png','.js','.class','.css')
doNotTrack = ('.jpg','.gif','.png','.js','.css')
def traverseWrapper(self, path, response=None, validated_hook=None):
'''This function is called every time a users gets a URL, this is used for
@ -67,12 +67,9 @@ class ZopeInstaller:
def installUi(self):
'''Installs the user interface.'''
# Some useful imports
# Some useful imports.
from OFS.Folder import manage_addFolder
from OFS.Image import manage_addImage, manage_addFile
from Products.PythonScripts.PythonScript import PythonScript
from Products.PageTemplates.ZopePageTemplate import \
manage_addPageTemplate
# Delete the existing folder if it existed.
zopeContent = self.app.objectIds()
if 'ui' in zopeContent: self.app.manage_delObjects(['ui'])
@ -99,33 +96,25 @@ class ZopeInstaller:
manage_addFolder(zopeFolder, name)
# Create files at this level
for name in files:
zopeName, ext = os.path.splitext(name)
if ext not in ('.pt', '.py'):
# In the ZODB, pages and scripts have their name without
# their extension.
zopeName = name
if hasattr(zopeFolder.aq_base, zopeName): continue
ext = os.path.splitext(name)[1]
if hasattr(zopeFolder.aq_base, name): continue
f = file(j(root, name))
if zopeName == 'favicon.ico':
if not hasattr(self.app, zopeName):
if name == 'favicon.ico':
if not hasattr(self.app, name):
# Copy it at the root. Else, IE won't notice it.
manage_addImage(self.app, zopeName, f)
manage_addImage(self.app, name, f)
elif ext in gen.File.imageExts:
manage_addImage(zopeFolder, zopeName, f)
elif ext == '.pt':
manage_addPageTemplate(zopeFolder,zopeName,'',f.read())
elif ext == '.py':
obj = PythonScript(zopeName)
zopeFolder._setObject(zopeName, obj)
zopeFolder._getOb(zopeName).write(f.read())
manage_addImage(zopeFolder, name, f)
else:
manage_addFile(zopeFolder, zopeName, f)
manage_addFile(zopeFolder, name, f)
f.close()
# Update the home page
if 'index_html' in zopeContent:
self.app.manage_delObjects(['index_html'])
from Products.PageTemplates.ZopePageTemplate import \
manage_addPageTemplate
manage_addPageTemplate(self.app, 'index_html', '', homePage)
# Update the error page
# Remove the error page.
if 'standard_error_message' in zopeContent:
self.app.manage_delObjects(['standard_error_message'])

View file

@ -50,11 +50,7 @@ pxDict = {
'r': 'pxRequired', 'c': 'pxChanges'}
# ------------------------------------------------------------------------------
class LayoutElement:
'''Abstract base class for any layout element.'''
def get(self): return self.__dict__
class Cell(LayoutElement):
class Cell:
'''Represents a cell in a row in a table.'''
def __init__(self, content, align, isHeader=False):
self.align = align
@ -84,7 +80,7 @@ class Cell(LayoutElement):
self.colspan = int(digits)
# ------------------------------------------------------------------------------
class Row(LayoutElement):
class Row:
'''Represents a row in a table.'''
def __init__(self, content, valign, isHeader=False):
self.valign = valign
@ -93,7 +89,7 @@ class Row(LayoutElement):
# Compute the row length
length = 0
for cell in self.cells:
length += cell['colspan']
length += cell.colspan
self.length = length
def decodeCells(self, content, isHeader):
@ -104,16 +100,16 @@ class Row(LayoutElement):
for char in content:
if char in cellDelimiters:
align = cellDelimiters[char]
self.cells.append(Cell(cellContent, align, isHeader).get())
self.cells.append(Cell(cellContent, align, isHeader))
cellContent = ''
else:
cellContent += char
# Manage the last cell if any
if cellContent:
self.cells.append(Cell(cellContent, 'left', isHeader).get())
self.cells.append(Cell(cellContent, 'left', isHeader))
# ------------------------------------------------------------------------------
class Table(LayoutElement):
class Table:
'''Represents a table where to dispose graphical elements.'''
simpleParams = ('style', 'css_class', 'cellpadding', 'cellspacing', 'width',
'align')
@ -193,27 +189,26 @@ class Table(LayoutElement):
valign = rowDelimiters[char]
if self.isHeaderRow(rowContent):
if not self.headerRow:
self.headerRow = Row(rowContent, valign,
isHeader=True).get()
self.headerRow = Row(rowContent, valign, isHeader=True)
else:
self.rows.append(Row(rowContent, valign).get())
self.rows.append(Row(rowContent, valign))
rowContent = ''
else:
rowContent += char
# Manage the last row if any
if rowContent:
self.rows.append(Row(rowContent, 'middle').get())
self.rows.append(Row(rowContent, 'middle'))
def removeElement(self, elem):
'''Removes given p_elem from myself.'''
macroToRemove = pxDict[elem]
for row in self.rows:
for cell in row['cells']:
if macroToRemove in cell['content']:
cell['content'].remove(macroToRemove)
for cell in row.cells:
if macroToRemove in cell.content:
cell.content.remove(macroToRemove)
# Some base layouts to use, for fields and pages -------------------------------
# The default layouts for pages
# The default layouts for pages.
defaultPageLayouts = {
'view': Table('w|-b|', align="center"),
'edit': Table('w|-b|', width=None)}

View file

@ -61,12 +61,12 @@ class ToolMixin(BaseMixin):
try:
url = tool.getHomePage()
except AttributeError:
# Bring Managers to the config, lead others to home.pt.
# Bring Managers to the config, lead others to pxHome.
user = self.getUser()
if user.has_role('Manager'):
url = self.goto(self.absolute_url())
else:
url = self.goto('%s/home' % self.getApp().config.absolute_url())
url = self.goto('%s/home' % self.absolute_url())
return url
def getHomeObject(self):
@ -96,12 +96,6 @@ class ToolMixin(BaseMixin):
'''Returns the absolute URL of this site.'''
return self.getApp().absolute_url()
def getPodInfo(self, obj, name):
'''Gets the available POD formats for Pod field named p_name on
p_obj.'''
podField = self.getAppyType(name, className=obj.meta_type)
return podField.getToolInfo(obj.appy())
def getIncludeUrl(self, name, bg=False):
'''Gets the full URL of an external resource, like an image, a
Javascript or a CSS file, named p_name. If p_bg is True, p_name is
@ -132,16 +126,6 @@ class ToolMixin(BaseMixin):
'inline;filename="%s"' % res.name)
return res.content
def getAttr(self, name, source='appy'):
'''Gets attribute named p_name.'''
if source == 'config':
obj = self.getProductConfig()
elif source == 'app':
obj = self.getProductConfig(True)
else:
obj = self.appy()
return getattr(obj, name, None)
def getAppName(self):
'''Returns the name of the application.'''
return self.getProductConfig().PROJECTNAME
@ -270,7 +254,7 @@ class ToolMixin(BaseMixin):
return res
def getResultMode(self, className):
'''Must we show, on result.pt, instances of p_className as a list or
'''Must we show, on pxQueryResult, instances of p_className as a list or
as a grid?'''
klass = self.getAppyClass(className)
if hasattr(klass, 'resultMode'): return klass.resultMode
@ -359,24 +343,20 @@ class ToolMixin(BaseMixin):
will be added to the query, or;
2) "customSearch": in this case, additional search criteria will
also be added to the query, but those criteria come from the
session (in key "searchCriteria") and were created from
search.pt.
session (in key "searchCriteria") and came from pxSearch.
We will retrieve objects from p_startNumber. If p_search is defined,
it corresponds to a custom Search instance (instead of a predefined
named search like in p_searchName). If both p_searchName and p_search
are given, p_search is ignored.
This method returns a list of objects in the form of the
__dict__ attribute of an instance of SomeObjects (see in
appy.gen.utils). We return the __dict__ attribute instead of real
instance: that way, it can be used in ZPTs without security problems.
If p_brainsOnly is True, it returns a list of brains instead (can be
useful for some usages like knowing the number of objects without
needing to get information about them). If no p_maxResults is
specified, the method returns maximum
self.numberOfResultsPerPage. The method returns all objects if
p_maxResults equals string "NO_LIMIT".
This method returns a list of objects in the form of an instance of
SomeObjects (see in appy.gen.utils). If p_brainsOnly is True, it
returns a list of brains instead (can be useful for some usages like
knowing the number of objects without needing to get information
about them). If no p_maxResults is specified, the method returns
maximum self.numberOfResultsPerPage. The method returns all objects
if p_maxResults equals string "NO_LIMIT".
If p_noSecurity is True, it gets all the objects, even those that the
currently logged user can't see.
@ -393,6 +373,7 @@ class ToolMixin(BaseMixin):
If p_refObject and p_refField are given, the query is limited to the
objects that are referenced from p_refObject through p_refField.'''
params = {'ClassName': className}
appyClass = self.getAppyClass(className, wrapper=True)
if not brainsOnly: params['batch'] = True
@ -447,7 +428,7 @@ class ToolMixin(BaseMixin):
i += 1
uids[startNumber+i] = obj.UID()
self.REQUEST.SESSION['search_%s' % searchName] = uids
return res.__dict__
return res
def getResultColumnsLayouts(self, className, refInfo):
'''Returns the column layouts for displaying objects of
@ -711,7 +692,7 @@ class ToolMixin(BaseMixin):
def onSearchObjects(self):
'''This method is called when the user triggers a search from
search.pt.'''
pxSearch.'''
rq = self.REQUEST
self.storeSearchCriteria()
# Go to the screen that displays search results

View file

@ -273,7 +273,7 @@ class BaseMixin:
def removeMyLock(self, user, page):
'''If p_user has set a lock on p_page, this method removes it. This
method is called when the user that locked a page consults
view.pt for this page. In this case, we consider that the user has
pxView for this page. In this case, we consider that the user has
left the edit page in an unexpected way and we remove the lock.'''
if hasattr(self.aq_base, 'locks') and (page in self.locks) and \
(user.login == self.locks[page][0]):
@ -670,69 +670,6 @@ class BaseMixin:
if not allValues: return ''
return getattr(allValues[rowIndex], name, '')
def getFileInfo(self, fileObject):
'''Returns filename and size of p_fileObject.'''
if not fileObject: return {'filename': '', 'size': 0}
return {'filename': fileObject.filename, 'size': fileObject.size}
def getAppyRefs(self, name, startNumber=None):
'''Gets the objects linked to me through Ref field named p_name.
If p_startNumber is None, this method returns all referred objects.
If p_startNumber is a number, this method will return
appyType.maxPerPage objects, starting at p_startNumber.'''
field = self.getAppyType(name)
return field.getValue(self, type='zobjects', someObjects=True,
startNumber=startNumber).__dict__
def getSelectableAppyRefs(self, name):
'''p_name is the name of a Ref field. This method returns the list of
all objects that can be selected to be linked as references to p_self
through field p_name.'''
appyType = self.getAppyType(name)
if not appyType.select:
# No select method has been defined: we must retrieve all objects
# of the referred type that the user is allowed to access.
return self.appy().search(appyType.klass)
else:
return appyType.select(self.appy())
xhtmlToText = re.compile('<.*?>', re.S)
def getReferenceLabel(self, name, refObject, className=None):
'''p_name is the name of a Ref field with 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
field.shownInfo is used.'''
appyType = self.getAppyType(name, className=className)
res = ''
for fieldName in appyType.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 = appyType.width or 30
if len(res) > maxWidth:
res = res[:maxWidth-2] + '...'
return res
def getReferenceUid(self, refObject):
'''Returns the UID of referred object p_refObject.'''
return refObject.o.UID()
def getAppyRefIndex(self, fieldName, obj):
'''Gets the position of p_obj within Ref field named p_fieldName.'''
refs = getattr(self.aq_base, fieldName, None)
if not refs: raise IndexError()
return refs.index(obj.UID())
def mayAddReference(self, name):
'''May the user add references via Ref field named p_name in
p_folder?'''
@ -1134,7 +1071,7 @@ class BaseMixin:
else:
event = history[i]
res.append(event)
return {'events': res, 'totalNumber': len(history)}
return Object(events=res, totalNumber=len(history))
def mayNavigate(self):
'''May the currently logged user see the navigation panel linked to
@ -1258,64 +1195,6 @@ class BaseMixin:
self.reindex()
return self.goto(self.getUrl(rq['HTTP_REFERER']))
def fieldValueSelected(self, fieldName, vocabValue, dbValue):
'''When displaying a selection box (ie a String with a validator being a
list), must the _vocabValue appear as selected?'''
rq = self.REQUEST
# Get the value we must compare (from request or from database)
if rq.has_key(fieldName):
compValue = rq.get(fieldName)
else:
compValue = dbValue
# Compare the value
if type(compValue) in sequenceTypes:
if vocabValue in compValue: return True
else:
if vocabValue == compValue: return True
def checkboxChecked(self, fieldName, dbValue):
'''When displaying a checkbox, must it be checked or not?'''
rq = self.REQUEST
# Get the value we must compare (from request or from database)
if rq.has_key(fieldName):
compValue = rq.get(fieldName)
compValue = compValue in ('True', 1, '1')
else:
compValue = dbValue
# Compare the value
return compValue
def dateValueSelected(self, fieldName, fieldPart, dateValue, dbValue):
'''When displaying a date field, must the particular p_dateValue be
selected in the field corresponding to the date part?'''
# Get the value we must compare (from request or from database)
rq = self.REQUEST
partName = '%s_%s' % (fieldName, 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 getSelectableYears(self, name):
'''Gets the list of selectable years for Date field named p_name.'''
return self.getAppyType(name).getSelectableYears()
def getPossibleValues(self, name, withTranslations, withBlankValue,
className=None):
'''See docstring of String.getPossibleValues.'''
field = self.getAppyType(name, className=className)
return field.getPossibleValues(self, withTranslations, withBlankValue,
className=className)
def getCaptchaChallenge(self, name):
return self.getAppyType(name).getCaptchaChallenge(self.REQUEST.SESSION)
def appy(self):
'''Returns a wrapper object allowing to manipulate p_self the Appy
way.'''
@ -1480,20 +1359,6 @@ class BaseMixin:
for permission, creators in allCreators.iteritems():
updateRolesForPermission(permission, tuple(creators), folder)
def _appy_getPortalType(self, request):
'''Guess the portal_type of p_self from info about p_self and
p_request.'''
res = None
# If the object is being created, self.portal_type is not correctly
# initialized yet.
if request.has_key('__factory__info__'):
factoryInfo = request['__factory__info__']
if factoryInfo.has_key('stack'):
res = factoryInfo['stack'][0]
if not res:
res = self.portal_type
return res
getUrlDefaults = {'page':True, 'nav':True}
def getUrl(self, base=None, mode='view', **kwargs):
'''Returns an URL for this object.
@ -1568,8 +1433,8 @@ class BaseMixin:
klass = self.getClass()
if hasattr(klass, 'breadcrumb') and not klass.breadcrumb: return ()
# Compute the breadcrumb
res = [{'url': self.absolute_url(),
'title': self.getFieldValue('title', layoutType='view')}]
res = [Object(url=self.absolute_url(),
title=self.getFieldValue('title', layoutType='view'))]
parent = self.getParent()
if parent:
res = parent.getBreadCrumb() + res
@ -1681,14 +1546,7 @@ class BaseMixin:
layout = Table(layout)
else:
layout = defaultPageLayouts[layoutType]
return layout.get()
def getPageTemplate(self, ui, templateName):
'''Returns, in the ui folder, the page template corresponding to
p_templateName.'''
res = ui
for name in templateName.split('/'): res = getattr(res, name)
return res
return layout
def download(self, name=None):
'''Downloads the content of the file that is in the File field whose
@ -1753,44 +1611,6 @@ class BaseMixin:
raise Unauthorized
return res
def getEditorInit(self, name):
'''Gets the Javascript init code for displaying a rich editor for
field named p_name.'''
# Define the attributes that will initialize the ckeditor instance for
# this field.
field = self.getAppyType(name)
ckAttrs = {'toolbar': 'Appy',
'format_tags': '%s' % ';'.join(field.styles)}
if field.width: ckAttrs['width'] = field.width
if field.allowImageUpload:
ckAttrs['filebrowserUploadUrl'] = '%s/upload' % self.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 getEditorInlineInit(self, name):
'''Gets the Javascript init code for enabling inline edition of a rich
field named p_name.'''
field = self.getAppyType(name)
uid = self.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, name, uid, name, self.absolute_url(), name)
def getCalendarInit(self, name, years):
'''Gets the Javascript init code for displaying a calendar popup for
field named p_name.'''
return 'Calendar.setup({inputField: "%s", button: "%s_img", ' \
'onSelect: onSelectDate, range:[%d,%d]});' % \
(name, name, years[0], years[-1])
def isTemporary(self):
'''Is this object temporary ?'''
parent = self.getParentNode()
@ -1802,11 +1622,4 @@ class BaseMixin:
'''This method is a general hook for transfering processing of a request
to a given field, whose name must be in the request.'''
return self.getAppyType(self.REQUEST['name']).process(self)
def callField(self, name, method, *args, **kwargs):
'''This method i a general hook for calling a p_method defined on a
field named p_name.'''
field = self.getAppyType(name)
exec 'res = field.%s(*args, **kwargs)' % method
return res
# ------------------------------------------------------------------------------

View file

@ -12,7 +12,7 @@ class Protos:
# List of attributes that can't be given to a Type constructor
notInit = ('id', 'type', 'pythonType', 'slaves', 'isSelect', 'hasLabel',
'hasDescr', 'hasHelp', 'required', 'filterable', 'validable',
'backd', 'isBack', 'sync', 'pageName', 'masterName')
'isBack', 'sync', 'pageName', 'masterName')
@classmethod
def get(self, appyType):
'''Returns a prototype instance for p_appyType.'''

View file

@ -1,34 +0,0 @@
<tal:comment replace="nothing">
This page is called by a XmlHttpRequest object. It requires parameters "page" and "macro":
they are used to call the macro that will render the HTML chunk to be returned to the browser.
It can also have a parameter "action", that refers to a method that will be triggered on
contextObj before returning the result of the macro to the browser.
</tal:comment>
<tal:ajax define="contextObj context/getParentNode;
tool contextObj/getTool;
_ python: contextObj.translate;
req python: request;
resp req/RESPONSE;
page req/page;
macro req/macro;
action req/action|nothing;
user contextObj/getUser;
app tool/getApp;
appUrl app/absolute_url;
template python: contextObj.getPageTemplate(app.ui, page);
lang tool/getUserLanguage;
dir python: tool.getLanguageDirection(lang);
dleft python: (dir == 'ltr') and 'left' or 'right';
dright python: (dir == 'ltr') and 'right' or 'left';
x python: resp.setHeader('Content-Type','text/html;;charset=utf-8');
x python: resp.setHeader('Expires', 'Mon, 11 Dec 1975 12:05:05 GMT');
x python: resp.setHeader('Content-Language', lang);
x python: resp.setHeader('CacheControl', 'no-cache')">
<tal:comment replace="nothing">Keys "Expires" and "CacheControl" are used for preventing IE to cache
this page. Indeed, this page is retrieved through an asynchronous XMLHttpRequest by the browser, and
IE caches this by default.</tal:comment>
<tal:executeAction condition="action">
<tal:do define="x python: contextObj.getMethod('on'+action)()" omit-tag=""/>
</tal:executeAction>
<metal:callMacro use-macro="python: template.macros.get(macro)"/>
</tal:ajax>

View file

@ -369,7 +369,7 @@ function initSlaves() {
}
}
// Function used to submit the appy form on edit.pt
// Function used to submit the appy form on pxEdit
function submitAppyForm(button) {
var theForm = document.getElementById('appyForm');
// On which button has the user clicked?

View file

@ -1,16 +0,0 @@
<tal:comment replace="nothing">
This page allows to call any macro from Python code, for example.
</tal:comment>
<tal:call tal:define="macroName options/macroName;
page python: options['page'];
contextObj python: options['contextObj'];
tool contextObj/getTool;
layoutType python:'view';
lang tool/getUserLanguage;
dir python: tool.getLanguageDirection(lang);
dleft python: (dir == 'ltr') and 'left' or 'right';
dright python: (dir == 'ltr') and 'right' or 'left';
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
phase phaseInfo/name;">
<metal:callMacro use-macro="python: page.macros[macroName]"/>
</tal:call>

View file

@ -1,43 +0,0 @@
<tal:main define="tool context/getTool">
<html metal:use-macro="context/ui/template/macros/main">
<metal:fill fill-slot="content"
tal:define="dummy python: contextObj.allows('Modify portal content', raiseError=True);
errors request/errors | python:{};
layout python: contextObj.getPageLayout(layoutType);
cssJs python: {};
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType=layoutType);
phase phaseInfo/name;
page request/page|python:contextObj.getDefaultEditPage();
dummy python: contextObj.setLock(user, page);
confirmMsg request/confirmMsg | nothing;
groupedWidgets python: contextObj.getGroupedAppyTypes(layoutType, page, cssJs=cssJs);"
tal:on-error="structure python: tool.manageError(error)">
<metal:prologue use-macro="context/ui/page/macros/prologue"/>
<tal:comment replace="nothing">Warn the user that the form should be left via buttons</tal:comment>
<script type="text/javascript">
window.onbeforeunload = function(e){
theForm = document.getElementById('appyForm');
if (theForm.button.value == "") {
var e = e || window.event;
if (e) {e.returnValue = warn_leave_form;}
return warn_leave_form;
}
}
</script>
<form id="appyForm" name="appyForm" method="post" enctype="multipart/form-data"
tal:attributes="action python: contextObj.absolute_url()+'/do'">
<input type="hidden" name="action" value="Update"/>
<input type="hidden" name="button" value=""/>
<input type="hidden" name="page" tal:attributes="value page"/>
<input type="hidden" name="nav" tal:attributes="value request/nav|nothing"/>
<input type="hidden" name="confirmed" value="False"/>
<metal:show use-macro="context/ui/page/macros/show"/>
</form>
<script tal:condition="confirmMsg" type="text/javascript"
tal:content="python: 'askConfirm(\'script\', \'postConfirmedEditForm()\', \'%s\')' % confirmMsg">
</script>
<metal:footer use-macro="context/ui/page/macros/footer"/>
</metal:fill>
</html>
</tal:main>

View file

@ -1,4 +0,0 @@
<table metal:define-macro="footer"
cellpadding="0" cellspacing="0" width="100%" class="footer">
<tr><td tal:attributes="align dright">Made with <a href="http://appyframework.org" target="_blank">Appy</a></td></tr>
</table>

View file

@ -1,9 +0,0 @@
<tal:main define="tool python: context.config">
<html metal:use-macro="context/ui/template/macros/main">
<table metal:fill-slot="content" width="300px" height="240px" align="center">
<tr valign="middle">
<td align="center" tal:content="structure python: tool.translate('front_page_text')"></td>
</tr>
</table>
</html>
</tal:main>

View file

@ -1,2 +0,0 @@
<metal:i define-macro="icons"></metal:i>
<metal:l define-macro="links"></metal:l>

View file

@ -1,109 +0,0 @@
<tal:main define="tool context/config">
<html metal:use-macro="context/ui/template/macros/main">
<metal:fill fill-slot="content"
tal:define="className request/className;
importElems python: tool.getImportElements(className);
global allAreImported python:True">
<div metal:use-macro="context/ui/page/macros/prologue"/>
<script type="text/javascript">
var importedElemsShown = false;
function toggleViewableElements() {
var rows = document.getElementsByName('importedElem');
var newDisplay = 'table-row';
if (isIe) newDisplay = 'block';
if (importedElemsShown) newDisplay = 'none';
for (var i=0; i<rows.length; i++) {
rows[i].style.display = newDisplay;
}
importedElemsShown = !importedElemsShown;
}
var checkBoxesChecked = true;
function toggleCheckboxes() {
var checkBoxes = document.getElementsByName('cbElem');
var newCheckValue = true;
if (checkBoxesChecked) newCheckValue = false;
for (var i=0; i<checkBoxes.length; i++) {
checkBoxes[i].checked = newCheckValue;
}
checkBoxesChecked = newCheckValue;
}
function importSingleElement(importPath) {
var f = document.forms['importElements'];
f.importPath.value = importPath;
f.submit();
}
function importManyElements() {
var f = document.forms['importElements'];
var importPaths = '';
// Get the values of the checkboxes
var checkBoxes = document.getElementsByName('cbElem');
for (var i=0; i<checkBoxes.length; i++) {
if (checkBoxes[i].checked) {
importPaths += checkBoxes[i].value + '|';
}
}
if (! importPaths) alert(no_elem_selected);
else {
f.importPath.value = importPaths;
f.submit();
}
}
</script>
<tal:comment replace="nothing">Form for importing several meetings at once.</tal:comment>
<form name="importElements"
tal:attributes="action python: tool.absolute_url()+'/do'" method="post">
<input type="hidden" name="action" value="ImportObjects"/>
<input type="hidden" name="className" tal:attributes="value className"/>
<input type="hidden" name="importPath" value=""/>
</form>
<h1 tal:content="python: _('import_title')"></h1><br/>
<table class="list" width="100%">
<tr>
<th tal:repeat="columnHeader python: importElems[0]">
<img tal:condition="python: repeat['columnHeader'].number() == 1"
tal:attributes="src string:$appUrl/ui/eye.png;
title python: _('import_show_hide')"
style="cursor:pointer" onClick="toggleViewableElements()" align="left" />
<span tal:replace="columnHeader"/>
</th>
<th></th>
<th width="20px"><img
tal:attributes="src string: $appUrl/ui/select_elems.png;
title python: _('select_delesect')"
onClick="toggleCheckboxes()" style="cursor:pointer"></th>
</tr>
<tal:row repeat="row python: importElems[1]">
<tr tal:define="alreadyImported python: tool.isAlreadyImported(className, row[0]);
global allAreImported python: allAreImported and alreadyImported;
odd repeat/row/odd"
tal:attributes="id python: alreadyImported and 'importedElem' or 'notImportedElem';
name python: alreadyImported and 'importedElem' or 'notImportedElem';
style python: alreadyImported and 'display:none' or 'display:table-row';
class python: odd and 'even' or 'odd'">
<td tal:repeat="elem python: row[1:]" tal:content="elem">
</td>
<td>
<input type="button" tal:condition="not: alreadyImported"
tal:attributes="onClick python: 'importSingleElement(\'%s\')' % row[0];
value python: _('query_import')"/>
<span tal:condition="alreadyImported" tal:replace="python: _('import_already')"/>
</td>
<td align="center">
<input type="checkbox" checked="checked" id="cbElem" name="cbElem"
tal:attributes="value python: row[0]" tal:condition="not: alreadyImported"/>
</td>
</tr>
</tal:row>
<tr tal:condition="python: not importElems[1] or allAreImported"><td colspan="15" tal:content="python: _('query_no_result')"></td></tr>
</table>
<tal:comment replace="nothing">Button for importing several elements at once.</tal:comment>
<p align="right"><br/>
<input type="button" onClick="importManyElements()"
tal:condition="python: importElems[1] and not allAreImported"
tal:attributes="value python: _('import_many')"/>
</p>
</metal:fill>
</html>
</tal:main>

View file

@ -1,143 +0,0 @@
<div metal:define-macro="appyNavigate" tal:condition="python: totalNumber &gt; batchSize" tal:attributes="align dright">
<tal:comment replace="nothing">
Buttons for navigating among a list of elements (next, back, first, last, etc).
</tal:comment>
<table class="listNavigate"
tal:define="mustSortAndFilter python: ajaxHookId == 'queryResult';
sortKey sortKey|python:'';
sortOrder sortOrder|python:'';
filterKey filterKey|python:'';
sortAndFilter python: test(mustSortAndFilter, ',\'%s\',\'%s\',\'%s\'' % (sortKey, sortOrder, filterKey), '')">
<tr valign="middle">
<tal:comment replace="nothing">Go to the first page</tal:comment>
<td tal:condition="python: (startNumber != 0) and (startNumber != batchSize)"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/arrowLeftDouble.png;
title python: _('goto_first');
onClick python: navBaseCall.replace('**v**', '0'+sortAndFilter)"/></td>
<tal:comment replace="nothing">Go to the previous page</tal:comment>
<td tal:define="sNumber python: startNumber - batchSize"
tal:condition="python: startNumber != 0"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png;
title python: _('goto_previous');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
<tal:comment replace="nothing">Explain which elements are currently shown</tal:comment>
<td class="discreet">&nbsp;
<span tal:replace="python: startNumber+1"/>
<img tal:attributes="src string: $appUrl/ui/to.png"/>
<span tal:replace="python: startNumber+len(objs)"/>&nbsp;<b>//</b>
<span tal:replace="python: totalNumber"/>&nbsp;&nbsp;
</td>
<tal:comment replace="nothing">Go to the next page</tal:comment>
<td tal:define="sNumber python: startNumber + batchSize"
tal:condition="python: sNumber &lt; totalNumber"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/arrowRightSimple.png;
title python: _('goto_next');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
<tal:comment replace="nothing">Go to the last page</tal:comment>
<td tal:define="lastPageIsIncomplete python: totalNumber % batchSize;
nbOfCompletePages python: totalNumber/batchSize;
nbOfCountedPages python: test(lastPageIsIncomplete, nbOfCompletePages, nbOfCompletePages-1);
sNumber python: (nbOfCountedPages*batchSize)"
tal:condition="python: (startNumber != sNumber) and (startNumber != sNumber-batchSize)"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/arrowRightDouble.png;
title python: _('goto_last');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
</tr>
</table>
</div>
<tal:comment replace="nothing">
Buttons for going to next/previous elements if this one is among bunch of referenced or searched objects.
currentNumber starts with 1.
</tal:comment>
<metal:nav define-macro="objectNavigate" tal:condition="request/nav|nothing">
<div tal:define="navInfo tool/getNavigationInfo;
currentNumber navInfo/currentNumber;
totalNumber navInfo/totalNumber;
firstUrl navInfo/firstUrl;
previousUrl navInfo/previousUrl;
nextUrl navInfo/nextUrl;
lastUrl navInfo/lastUrl;
sourceUrl navInfo/sourceUrl;
backText navInfo/backText">
<tal:comment replace="nothing">Go to the source URL (search or referred object)</tal:comment>
<a tal:condition="sourceUrl" tal:attributes="href sourceUrl"><img
tal:define="gotoSource python: _('goto_source');
goBack python: backText and ('%s - %s' % (backText, gotoSource)) or gotoSource"
tal:attributes="src string: $appUrl/ui/gotoSource.png; title goBack"/></a>
<tal:comment replace="nothing">Go to the first page</tal:comment>
<a tal:condition="firstUrl" tal:attributes="href firstUrl"><img
tal:attributes="src string: $appUrl/ui/arrowLeftDouble.png;
title python: _('goto_first')"/></a>
<tal:comment replace="nothing">Go to the previous page</tal:comment>
<a tal:condition="previousUrl" tal:attributes="href previousUrl"><img
tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png;
title python: _('goto_previous')"/></a>
<tal:comment replace="nothing">Explain which element is currently shown</tal:comment>
<span class="discreet">&nbsp;
<span tal:replace="python: currentNumber"/>&nbsp;<b>//</b>
<span tal:replace="python: totalNumber"/>&nbsp;&nbsp;
</span>
<tal:comment replace="nothing">Go to the next page</tal:comment>
<a tal:condition="python: nextUrl" tal:attributes="href nextUrl"><img
tal:attributes="src string: $appUrl/ui/arrowRightSimple.png;
title python: _('goto_next')"/></a>
<tal:comment replace="nothing">Go to the last page</tal:comment>
<a tal:condition="lastUrl" tal:attributes="href lastUrl"><img
tal:attributes="src string: $appUrl/ui/arrowRightDouble.png;
title python: _('goto_last')"/></a>
</div>
</metal:nav>
<table metal:define-macro="navigationStrip" tal:condition="python: contextObj"
width="100%" class="navigate">
<tr>
<td tal:define="breadcrumb contextObj/getBreadCrumb" class="breadcrumb">
<tal:bc repeat="bc breadcrumb">
<tal:elem define="nb repeat/bc/number">
<tal:sep condition="python: nb != 1">
<img tal:attributes="src string: $appUrl/ui/to.png"/>
</tal:sep>
<tal:comment replace="nothing">Display only the title of the current object</tal:comment>
<span tal:condition="python: nb == len(breadcrumb)" tal:content="bc/title"></span>
<tal:comment replace="nothing">Display a link for parent objects</tal:comment>
<a tal:condition="python: nb != len(breadcrumb)" tal:attributes="href bc/url" tal:content="bc/title"></a>
</tal:elem>
</tal:bc>
</td>
<td align="right">
<metal:nav use-macro="app/ui/navigate/macros/objectNavigate"/>
</td>
</tr>
</table>
<tal:comment replace="nothing">
This macro displays up/down arrows in a table header column for sorting a given column.
It requires variables "sortable", 'filterable' and 'fieldName'.
</tal:comment>
<metal:sortAndFilter define-macro="sortAndFilter" tal:define="fieldName widget/name">
<tal:sort condition="sortable">
<img tal:attributes="src string: $appUrl/ui/sortDown.gif;
onClick python: navBaseCall.replace('**v**', '0,\'%s\',\'asc\',\'%s\'' % (fieldName, filterKey))"
tal:condition="python: (sortKey != fieldName) or (sortOrder == 'desc')"
style="cursor:pointer"/>
<img tal:attributes="src string: $appUrl/ui/sortUp.gif;
onClick python: navBaseCall.replace('**v**', '0,\'%s\',\'desc\',\'%s\'' % (fieldName, filterKey))"
tal:condition="python: (sortKey != fieldName) or (sortOrder == 'asc')"
style="cursor:pointer"/>
</tal:sort>
<tal:filter condition="filterable">
<input type="text" size="7"
tal:attributes="id python: '%s_%s' % (ajaxHookId, fieldName);
value python: test(filterKey == fieldName, filterValue, '')"/>
<img tal:attributes="src string: $appUrl/ui/funnel.png;
onClick python: navBaseCall.replace('**v**', '0,\'%s\',\'%s\',\'%s\'' % (sortKey, sortOrder, fieldName))"
style="cursor:pointer"/>
</tal:filter>
</metal:sortAndFilter>
<tal:comment replace="nothing">Icon for hiding/showing details below the title</tal:comment>
<metal:details define-macro="showDetails" tal:condition="python: tool.subTitleIsUsed(className)">
<img tal:condition="python: widget['name'] == 'title'" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/toggleDetails.png" onClick="toggleSubTitles()"/>
</metal:details>

View file

@ -1,369 +0,0 @@
<tal:comment replace="nothing">
This macro contains global page-related Javascripts.
</tal:comment>
<div metal:define-macro="prologue">
<tal:comment replace="nothing">Include type-specific CSS and JS.</tal:comment>
<tal:include condition="cssJs|nothing">
<link tal:repeat="cssFile cssJs/css" rel="stylesheet" type="text/css"
tal:attributes="href string:$appUrl/ui/$cssFile"/>
<script tal:repeat="jsFile cssJs/js" type="text/javascript"
tal:attributes="src string:$appUrl/ui/$jsFile"></script>
</tal:include>
<tal:comment replace="nothing">Javascript messages</tal:comment>
<script type="text/javascript" tal:content="tool/getJavascriptMessages"></script>
<tal:comment replace="nothing">Global form for deleting an object</tal:comment>
<form id="deleteForm" method="post" action="do">
<input type="hidden" name="action" value="Delete"/>
<input type="hidden" name="objectUid"/>
</form>
<tal:comment replace="nothing">Global form for deleting an event from an object's history</tal:comment>
<form id="deleteEventForm" method="post" action="do">
<input type="hidden" name="action" value="DeleteEvent"/>
<input type="hidden" name="objectUid"/>
<input type="hidden" name="eventTime"/>
</form>
<tal:comment replace="nothing">Global form for unlinking an object</tal:comment>
<form id="unlinkForm" method="post" action="do">
<input type="hidden" name="action" value="Unlink"/>
<input type="hidden" name="sourceUid"/>
<input type="hidden" name="fieldName"/>
<input type="hidden" name="targetUid"/>
</form>
<tal:comment replace="nothing">Global form for unlocking a page</tal:comment>
<form id="unlockForm" method="post" action="do">
<input type="hidden" name="action" value="Unlock"/>
<input type="hidden" name="objectUid"/>
<input type="hidden" name="pageName"/>
</form>
<tal:comment replace="nothing">Global form for generating a document from a pod template</tal:comment>
<form id="podTemplateForm" name="podTemplateForm" method="post"
tal:attributes="action python: tool.absolute_url() + '/generateDocument'">
<input type="hidden" name="objectUid"/>
<input type="hidden" name="fieldName"/>
<input type="hidden" name="podFormat"/>
<input type="hidden" name="askAction"/>
<input type="hidden" name="queryData"/>
<input type="hidden" name="customParams"/>
</form>
</div>
<tal:comment replace="nothing">
This macro shows the content of page. Because a page is a layouted object,
we simply call the macro that displays a layouted object.
contextObj The Zope object for which this page must be shown
layoutType The kind of layout: "view"? "edit"? "cell"?
layout The layout object that will dictate how object content
will be rendered.
</tal:comment>
<metal:show define-macro="show" tal:define="tagId python: 'pageLayout'">
<metal:layout use-macro="context/ui/widgets/show/macros/layout"/>
</metal:show>
<tal:comment replace="nothing">
This macro displays all widgets of a given page. It requires:
contextObj The Zope object for which widgets must be shown
page We show widgets of a given page
layoutType We must know if we must render the widgets in a "view",
"edit" or "cell" layout
</tal:comment>
<table metal:define-macro="widgets"
tal:attributes="width layout/width">
<tr tal:repeat="widget groupedWidgets">
<td tal:condition="python: widget['type'] == 'group'">
<metal:call use-macro="app/ui/widgets/show/macros/group"/>
</td>
<td tal:condition="python: widget['type'] != 'group'">
<metal:call use-macro="app/ui/widgets/show/macros/field"/>
</td>
</tr>
</table>
<tal:comment replace="nothing">
This macro displays an object's history. It is used by macro "header" below.
</tal:comment>
<metal:history define-macro="objectHistory"
tal:define="startNumber request/startNumber|python:0;
startNumber python: int(startNumber);
batchSize python: int(request.get('maxPerPage', 5));
historyInfo python: contextObj.getHistory(startNumber, batchSize=batchSize);
objs historyInfo/events;
totalNumber historyInfo/totalNumber;
ajaxHookId python:'appyHistory';
navBaseCall python: 'askObjectHistory(\'%s\',\'%s\',%d,**v**)' % (ajaxHookId, contextObj.absolute_url(),batchSize);
tool contextObj/getTool;
_ python: tool.translate">
<tal:comment replace="nothing">Table containing the history</tal:comment>
<tal:history condition="objs">
<metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/>
<table width="100%" class="history">
<tr>
<th tal:attributes="align dleft" tal:content="python: _('object_action')"></th>
<th tal:attributes="align dleft" tal:content="python: _('object_author')"></th>
<th tal:attributes="align dleft" tal:content="python: _('action_date')"></th>
<th tal:attributes="align dleft" tal:content="python: _('action_comment')"></th>
</tr>
<tal:event repeat="event objs">
<tr tal:define="odd repeat/event/odd;
rhComments event/comments|nothing;
state event/review_state|nothing;
isDataChange python: event['action'] == '_datachange_'"
tal:attributes="class python:test(odd, 'even', 'odd')" valign="top">
<td tal:condition="isDataChange">
<span tal:content="python: _('data_change')"></span>
<img tal:condition="python: user.has_role('Manager')" style="cursor:pointer"
tal:attributes="src string:$appUrl/ui/delete.png;
onClick python: 'onDeleteEvent(\'%s\', \'%s\')' % (contextObj.UID(), event['time'])"/>
</td>
<td tal:condition="not: isDataChange"
tal:content="python: _(contextObj.getWorkflowLabel(event['action']))"/>
<td tal:define="actorId python:event.get('actor')">
<span tal:condition="not: actorId" tal:replace="python: '?'"/>
<span tal:condition="actorId" tal:content="python: tool.getUserName(actorId)"></span>
</td>
<td tal:content="python: tool.formatDate(event['time'], withHour=True)"/>
<td tal:condition="not: isDataChange">
<tal:c condition="rhComments"
content="structure python: contextObj.formatText(rhComments)"/>
<span tal:condition="not: rhComments">-</span>
</td>
<td tal:condition="isDataChange">
<tal:comment replace="nothing">
Display the previous values of the fields whose value were modified in this change.</tal:comment>
<table class="appyChanges" width="100%">
<tr>
<th tal:attributes="align dleft" width="30%" tal:content="python: _('modified_field')"></th>
<th tal:attributes="align dleft" width="70%" tal:content="python: _('previous_value')"></th>
</tr>
<tr tal:repeat="change event/changes/items" valign="top">
<tal:change define="appyType python:contextObj.getAppyType(change[0], asDict=True);">
<td tal:content="structure python: _(appyType['labelId'])"></td>
<td tal:content="structure python:change[1][0]"></td>
</tal:change>
</tr>
</table>
</td>
</tr>
</tal:event>
</table>
</tal:history>
</metal:history>
<tal:comment replace="nothing">
This macro displays an object's transitions(s). It is used by macro "header" below.
</tal:comment>
<metal:transitions define-macro="transitions"
tal:define="transitions targetObj/getAppyTransitions"
tal:condition="transitions">
<form tal:define="formId python: 'trigger_%s' % targetObj.UID()" method="post"
tal:attributes="id formId; action python: targetObj.absolute_url() + '/do'">
<input type="hidden" name="action" value="Trigger"/>
<input type="hidden" name="workflow_action"/>
<table>
<tr valign="middle">
<tal:comment replace="nothing">Input field for storing comment</tal:comment>
<textarea id="comment" name="comment" cols="30" rows="3" style="display:none"></textarea>
<tal:comment replace="nothing">Buttons for triggering transitions</tal:comment>
<td tal:attributes="align dright" tal:repeat="transition transitions">
<tal:comment replace="nothing">Real button</tal:comment>
<input type="button" class="button" tal:condition="transition/may_trigger"
tal:attributes="style string: background-image: url($appUrl/ui/buttonTransition.png);
title transition/title;
value python: tool.truncateValue(transition['title']);
onClick python: 'triggerTransition(\'%s\',\'%s\',\'%s\')' % (formId,transition['name'],transition['confirm'])">
<tal:comment replace="nothing">Fake button, explaining why the transition can't be triggered</tal:comment>
<input type="button" class="button" tal:condition="not: transition/may_trigger"
tal:attributes="style string: background-image: url($appUrl/ui/buttonFake.png);; cursor: help;
value python: tool.truncateValue(transition['title']);
title python: '%s: %s' % (transition['title'], transition['reason'])"/>
</td>
</tr>
</table>
</form>
</metal:transitions>
<tal:comment replace="nothing">
This macros displays the page header, containing object title,
workflow-related info, object history, etc.
</tal:comment>
<div metal:define-macro="header"
tal:define="hasHistory contextObj/hasHistory;
historyMaxPerPage options/maxPerPage|python: 5;
historyExpanded python: request.get('appyHistory', 'collapsed') == 'expanded';
_ python: tool.translate;
creator contextObj/Creator"
tal:condition="not: contextObj/isTemporary">
<tal:comment replace="nothing">Information that is common to all tabs (object title, state, etc)</tal:comment>
<table width="100%" class="summary">
<tr>
<td colspan="2" class="by">
<tal:comment replace="nothing">Creator and last modification date</tal:comment>
<tal:comment replace="nothing">Plus/minus icon for accessing history</tal:comment>
<tal:accessHistory condition="hasHistory">
<img style="cursor:pointer" onClick="toggleCookie('appyHistory')"
tal:attributes="src python:test(historyExpanded, 'ui/collapse.gif', 'ui/expand.gif');
align dleft"
id="appyHistory_img"/>&nbsp;
<span tal:replace="python: _('object_history')"></span> ||&nbsp;
</tal:accessHistory>
<tal:comment replace="nothing">Document creator</tal:comment>
<tal:creator>
<tal:by replace="python: _('object_created_by')"/>
<tal:creator replace="python: tool.getUserName(creator)"/>
</tal:creator>
<tal:comment replace="nothing">Creation and last modification dates</tal:comment>
<tal:by replace="python: _('object_created_on')"/>
<tal:dates define="creationDate contextObj/Created;
modificationDate contextObj/Modified">
<tal:date replace="python: tool.formatDate(creationDate, withHour=True)"/>
<tal:modified condition="python: modificationDate != creationDate">&mdash;
<tal:by replace="python: _('object_modified_on')"/>
<tal:date replace="python: tool.formatDate(modificationDate, withHour=True)"/>
</tal:modified>
</tal:dates>
<tal:comment replace="nothing">State</tal:comment>
<tal:state condition="contextObj/showState">
&mdash;
<tal:label replace="python: _('workflow_state')"/>:
<b tal:content="python: _(contextObj.getWorkflowLabel())"></b>
</tal:state>
</td>
</tr>
<tal:comment replace="nothing">Object history</tal:comment>
<tr tal:condition="hasHistory">
<td colspan="2">
<span id="appyHistory"
tal:attributes="style python:test(historyExpanded, 'display:block', 'display:none')">
<div tal:define="ajaxHookId python: contextObj.UID() + '_history';"
tal:attributes="id ajaxHookId">
<script type="text/javascript"
tal:content="python: 'askObjectHistory(\'%s\',\'%s\',%d,0)' % (ajaxHookId, contextObj.absolute_url(),historyMaxPerPage)">
</script>
</div>
</span>
</td>
</tr>
</table>
</div>
<tal:comment replace="nothing">The page footer.</tal:comment>
<metal:footer define-macro="footer">
<script type="text/javascript">initSlaves();</script>
</metal:footer>
<tal:comment replace="nothing">
This macro shows the range of buttons (next, previous, save,...) and the workflow transitions.
</tal:comment>
<table metal:define-macro="buttons" cellpadding="2" cellspacing="0" style="margin-top: 7px"
tal:define="previousPage python: contextObj.getPreviousPage(phaseInfo, page)[0];
nextPage python: contextObj.getNextPage(phaseInfo, page)[0];
isEdit python: layoutType == 'edit';
pageInfo python: phaseInfo['pagesInfo'][page]">
<tr>
<tal:comment replace="nothing">Previous</tal:comment>
<td tal:condition="python: previousPage and pageInfo['showPrevious']">
<tal:button condition="isEdit">
<input type="button" class="button" onClick="submitAppyForm('previous')"
tal:attributes="style string: background-image: url($appUrl/ui/buttonPrevious.png);
value python: _('page_previous')">
<input type="hidden" name="previousPage" tal:attributes="value previousPage"/>
</tal:button>
<tal:link condition="not: isEdit">
<input type="button" class="button"
tal:attributes="style string: background-image: url($appUrl/ui/buttonPrevious.png);
value python: _('page_previous');
onclick python: 'window.location=\'%s\'' % contextObj.getUrl(page=previousPage)">
</tal:link>
</td>
<tal:comment replace="nothing">Save</tal:comment>
<td tal:condition="python: isEdit and pageInfo['showSave']">
<input type="button" class="button" onClick="submitAppyForm('save')"
tal:attributes="style string: background-image: url($appUrl/ui/buttonSave.png);
value python: _('object_save')">
</td>
<tal:comment replace="nothing">Cancel</tal:comment>
<td tal:condition="python: isEdit and pageInfo['showCancel']">
<input type="button" class="button" onClick="submitAppyForm('cancel')"
tal:attributes="style string: background-image: url($appUrl/ui/buttonCancel.png);
value python: _('object_cancel')">
</td>
<tal:edit condition="not: isEdit">
<td tal:define="locked python: contextObj.isLocked(user, page);
editable python: pageInfo['showOnEdit'] and contextObj.mayEdit()">
<tal:comment replace="nothing">Edit</tal:comment>
<input type="button" class="button" tal:condition="python: editable and not locked and pageInfo['showEdit']"
tal:attributes="style string: background-image: url($appUrl/ui/buttonEdit.png);
value python: _('object_edit');
onclick python: 'window.location=\'%s\'' % contextObj.getUrl(mode='edit', page=page)">
<tal:comment replace="nothing">Locked</tal:comment>
<a tal:condition="python: editable and locked and pageInfo['showEdit']">
<img style="cursor: help"
tal:define="lockDate python: tool.formatDate(locked[1]);
lockMsg python: _('page_locked', mapping={'user':tool.getUserName(locked[0]), 'date': lockDate})"
tal:attributes="src string: $appUrl/ui/lockedBig.png; title lockMsg"/>
</a>
</td>
</tal:edit>
<tal:comment replace="nothing">Next</tal:comment>
<td tal:condition="python: nextPage and pageInfo['showNext']">
<tal:button condition="isEdit">
<input type="button" class="button" onClick="submitAppyForm('next')"
tal:attributes="style string: background-image: url($appUrl/ui/buttonNext.png);
value python: _('page_next')">
<input type="hidden" name="nextPage" tal:attributes="value nextPage"/>
</tal:button>
<tal:link condition="not: isEdit">
<input type="button" class="button"
tal:attributes="style string: background-image: url($appUrl/ui/buttonNext.png);
value python: _('page_next');
onclick python: 'window.location=\'%s\'' % contextObj.getUrl(page=nextPage)">
</tal:link>
</td>
<tal:comment replace="nothing">Workflow transitions</tal:comment>
<td tal:define="targetObj python: contextObj"
tal:condition="python: targetObj.showTransitions(layoutType)">
<metal:transitions use-macro="app/ui/page/macros/transitions"/>
</td>
<tal:comment replace="nothing">Refresh</tal:comment>
<td tal:condition="contextObj/isDebug">
<a tal:attributes="href python: contextObj.getUrl(mode=layoutType, page=page, refresh='yes')">
<img title="Refresh" style="vertical-align:top"
tal:attributes="src string: $appUrl/ui/refresh.png"/>
</a>
</td>
</tr>
</table>
<tal:comment replace="nothing">
This macro displays the global message on the page.
</tal:comment>
<metal:message define-macro="message" tal:define="messages tool/consumeMessages" tal:condition="messages">
<div class="message">
<img tal:attributes="src python: '%s/ui/close.png' % appUrl"
align="right" style="cursor:pointer" onClick="this.parentNode.style.display='none'"/>
<span tal:replace="structure messages"></span>
</div>
</metal:message>
<tal:comment replace="nothing">
Save the content of a rich field and return its consult view.
Requires request/fieldContent.
</tal:comment>
<metal:save define-macro="saveField"
tal:define="fieldName request/fieldName;
fieldContent request/fieldContent;
dummy python: contextObj.updateField(fieldName, fieldContent)">
<metal:call use-macro="app/ui/widgets/show/macros/fieldAjax"/>
</metal:save>

View file

@ -1,184 +0,0 @@
<tal:comment replace="nothing">Macro for displaying a search</tal:comment>
<div metal:define-macro="search" class="portletSearch">
<a tal:attributes="href python: '%s?className=%s&search=%s' % (queryUrl, rootClass, search['name']);
title search/translatedDescr;
class python: test(search['name'] == currentSearch, 'portletCurrent', '');"
tal:content="search/translated">
</a>
</div>
<tal:comment replace="nothing">Macro for displaying a group of searches</tal:comment>
<metal:group define-macro="group"
tal:define="expanded python: request.get(widget['labelId'], 'collapsed') == 'expanded'">
<tal:comment replace="nothing">Group name</tal:comment>
<div class="portletGroup">
<img style="cursor:pointer; margin-right: 3px"
tal:attributes="id python: '%s_img' % widget['labelId'];
src python:test(expanded, 'ui/collapse.gif', 'ui/expand.gif');
onClick python:'toggleCookie(\'%s\')' % widget['labelId'];
align dleft"/>
<span tal:condition="not: widget/translated" tal:replace="python: _(widget['labelId'])"/>
<span tal:condition="widget/translated" tal:replace="widget/translated"/>
</div>
<tal:comment replace="nothing">Group content</tal:comment>
<div tal:define="display python:test(expanded, 'display:block', 'display:none')"
tal:attributes="id widget/labelId;
style python: 'padding-left: 10px;; %s' % display">
<tal:searchRows repeat="searches widget/widgets">
<tal:searchElem repeat="searchElem searches">
<tal:comment replace="nothing">An inner group within this group</tal:comment>
<tal:group condition="python: searchElem['type'] == 'group'">
<tal:g define="widget searchElem">
<metal:s use-macro="app/ui/portlet/macros/group"/>
</tal:g>
</tal:group>
<tal:search condition="python: searchElem['type'] != 'group'">
<tal:s define="search searchElem">
<metal:s use-macro="app/ui/portlet/macros/search"/>
</tal:s>
</tal:search>
</tal:searchElem>
</tal:searchRows>
</div>
</metal:group>
<tal:comment replace="nothing">Macro displaying the whole portlet</tal:comment>
<metal:portlet define-macro="portlet"
tal:define="queryUrl python: '%s/ui/query' % tool.absolute_url();
toolUrl tool/absolute_url;
app tool/getApp;
appUrl app/absolute_url;
currentSearch req/search|nothing;
currentClass req/className|nothing;
currentPage python: req['PATH_INFO'].rsplit('/',1)[-1];
rootClasses tool/getRootClasses;
phases python: contextObj and contextObj.getAppyPhases() or None">
<tal:phases condition="python: contextObj and phases and contextObj.mayNavigate()">
<metal:phases use-macro="app/ui/portlet/macros/phases"/>
</tal:phases>
<tal:comment replace="nothing">One section for every searchable root class.</tal:comment>
<tal:section repeat="rootClass python: [rc for rc in rootClasses if tool.userMaySearch(rc)]">
<tal:comment replace="nothing">A separator if required</tal:comment>
<div class="portletSep" tal:define="nb repeat/rootClass/number"
tal:condition="python: (nb != 1) or ((nb == 1) and phases)"></div>
<div class="portletContent" tal:define="searchInfo python: tool.getGroupedSearches(rootClass)">
<tal:comment replace="nothing">Section title (link triggers the default search)</tal:comment>
<div class="portletTitle">
<a tal:define="queryParam python: searchInfo['default'] and searchInfo['default']['name'] or ''"
tal:attributes="href python: '%s?className=%s&search=%s' % (queryUrl, rootClass, queryParam);
class python: (not currentSearch and (currentClass==rootClass) and (currentPage=='query')) and 'portletCurrent' or ''"
tal:content="structure python: _(rootClass + '_plural')">
</a>
</div>
<tal:actions define="addPermission python: '%s: Add %s' % (appName, rootClass);
userMayAdd python: user.has_permission(addPermission, appFolder);
createMeans python: tool.getCreateMeans(rootClass)">
<tal:comment replace="nothing">Create a new object from a web form</tal:comment>
<input type="button" class="button" tal:condition="python: userMayAdd and ('form' in createMeans)"
tal:attributes="style string: background-image: url($appUrl/ui/buttonAdd.png);
value python: _('query_create');
onclick python: 'window.location=\'%s/do?action=Create&className=%s\'' % (toolUrl, rootClass)">
<tal:comment replace="nothing">Create object(s) by importing data</tal:comment>
<input type="button" class="button" tal:condition="python: userMayAdd and ('import' in createMeans)"
tal:attributes="style string: background-image: url($appUrl/ui/buttonImport.png);
value python: _('query_import');
onclick python: 'window.location=\'%s/ui/import?className=%s\'' % (toolUrl, rootClass)">
</tal:actions>
<tal:search condition="python: tool.advancedSearchEnabledFor(rootClass)">
<tal:comment replace="nothing">Live search</tal:comment>
<form tal:attributes="action string: $appUrl/config/do">
<input type="hidden" name="action" value="SearchObjects"/>
<input type="hidden" name="className" tal:attributes="value rootClass"/>
<table cellpadding="0" cellspacing="0">
<tr valign="bottom">
<td><input type="text" size="14" name="w_SearchableText" class="inputSearch"/></td>
<td><input type="image" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/search.gif;
title python: _('search_button')"/></td>
</tr>
</table>
</form>
<tal:comment replace="nothing">Advanced search</tal:comment>
<div tal:define="highlighted python: (currentClass == rootClass) and (currentPage == 'search')"
tal:attributes="class python: highlighted and 'portletSearch portletCurrent' or 'portletSearch';
align dright">
<a tal:define="text python: _('search_title')" style="font-size: 88%"
tal:attributes="href python: '%s/ui/search?className=%s' % (toolUrl, rootClass); title text">
<span tal:replace="text"/>...
</a>
</div>
</tal:search>
<tal:comment replace="nothing">Predefined searches</tal:comment>
<tal:widget repeat="widget searchInfo/searches">
<tal:group condition="python: widget['type'] == 'group'">
<metal:s use-macro="app/ui/portlet/macros/group"/>
</tal:group>
<tal:search condition="python: widget['type'] != 'group'">
<tal:s define="search widget">
<metal:s use-macro="app/ui/portlet/macros/search"/>
</tal:s>
</tal:search>
</tal:widget>
</div>
</tal:section>
</metal:portlet>
<tal:comment replace="nothing">
This macro displays, within the portlet, the navigation tree for the
currently shown object, made of phases and contained pages.
</tal:comment>
<table metal:define-macro="phases" class="portletContent"
tal:define="singlePhase python: phases and (len(phases) == 1);
page python: req.get('page', '');
mayEdit contextObj/mayEdit">
<tal:phase repeat="phase phases">
<tal:comment replace="nothing">The box containing phase-related information</tal:comment>
<tr tal:define="singlePage python: len(phase['pages']) == 1">
<td tal:define="label python:'%s_phase_%s' % (contextObj.meta_type, phase['name'])">
<tal:comment replace="nothing">The title of the phase</tal:comment>
<div class="portletGroup" tal:condition="python: not singlePhase and not singlePage"
tal:content="structure python: _(label)">
</div>
<tal:comment replace="nothing">The page(s) within the phase</tal:comment>
<tal:page repeat="aPage phase/pages">
<tal:comment replace="nothing">First line: page name and icons</tal:comment>
<div tal:condition="python: not (singlePhase and singlePage)"
tal:attributes="class python: test(aPage == page, 'portletCurrent portletPage', 'portletPage')">
<a tal:attributes="href python: contextObj.getUrl(page=aPage)"
tal:content="structure python: _('%s_page_%s' % (contextObj.meta_type, aPage))">
</a>
<tal:icons define="locked python: contextObj.isLocked(user, aPage);
editable python: mayEdit and phase['pagesInfo'][aPage]['showOnEdit']">
<a tal:condition="python: editable and not locked"
tal:attributes="href python: contextObj.getUrl(mode='edit', page=aPage)">
<img tal:attributes="src string: $appUrl/ui/edit.png;
title python: _('object_edit')"/>
</a>
<a tal:condition="python: editable and locked">
<img style="cursor: help"
tal:define="lockDate python: tool.formatDate(locked[1]);
lockMsg python: _('page_locked', mapping={'user':tool.getUserName(locked[0]), 'date': lockDate})"
tal:attributes="src string: $appUrl/ui/locked.png; title lockMsg"/></a>
<a tal:condition="python: editable and locked and user.has_role('Manager')">
<img style="cursor: pointer"
tal:attributes="src string: $appUrl/ui/unlock.png;
title python: _('page_unlock');
onclick python: 'onUnlockPage(\'%s\',\'%s\')' % (contextObj.UID(), aPage)"/></a>
</tal:icons>
</div>
<tal:comment replace="nothing">Next lines: links</tal:comment>
<tal:links define="links python: phase['pagesInfo'][aPage].get('links')" tal:condition="links">
<div tal:repeat="link links">
<a tal:content="link/title" tal:attributes="href link/url"></a>
</div>
</tal:links>
</tal:page>
</td>
</tr>
</tal:phase>
</table>

View file

@ -1,10 +0,0 @@
<tal:main define="tool python: context.config">
<html metal:use-macro="context/ui/template/macros/main">
<metal:fill fill-slot="content"
tal:define="className request/className;
searchName request/search|python:''">
<div metal:use-macro="context/ui/page/macros/prologue"/>
<metal:result use-macro="tool/ui/result/macros/queryResult"/>
</metal:fill>
</html>
</tal:main>

View file

@ -1,178 +0,0 @@
<tal:comment replace="nothing">Show field content of a given object.</tal:comment>
<metal:field define-macro="field">
<tal:comment replace="nothing">Title</tal:comment>
<tal:title condition="python: widget['name'] == 'title'">
<tal:nav define="navInfo python:'search.%s.%s.%d.%d' % (className, searchName, startNumber+currentNumber, totalNumber);
cssClass python: obj.getCssFor('title')">
<tal:sup replace="structure python: obj.getSupTitle(navInfo)"/>
<a tal:content="obj/Title" tal:condition="enableLinks"
tal:attributes="href python: obj.getUrl(nav=navInfo, page=obj.getDefaultViewPage()); class cssClass"></a><span
tal:condition="not: enableLinks" tal:attributes="class cssClass" tal:content="obj/Title"></span><span
name="subTitle" tal:content="structure obj/getSubTitle"
tal:attributes="style python: showSubTitles and 'display:inline' or 'display:none'"></span>
<tal:comment replace="nothing">Actions: edit, delete</tal:comment>
<div tal:condition="obj/mayAct">
<a tal:define="navInfo python:'search.%s.%s.%d.%d' % (className, searchName, repeat['obj'].number()+startNumber, totalNumber);"
tal:attributes="href python: obj.getUrl(mode='edit', page=obj.getDefaultEditPage(), nav=navInfo)"
tal:condition="obj/mayEdit">
<img tal:attributes="src string: $appUrl/ui/edit.png;
title python: _('object_edit')"/></a><img
tal:condition="obj/mayDelete" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/delete.png;
title python: _('object_delete');
onClick python:'onDeleteObject(\'%s\')' % obj.UID()"/>
</div>
</tal:nav>
</tal:title>
<tal:comment replace="nothing">Any other field</tal:comment>
<tal:other condition="python: widget['name'] != 'title'">
<tal:field define="contextObj python:obj;
layoutType python:'cell';
innerRef python:True"
condition="python: contextObj.showField(widget['name'], 'result')">
<metal:f use-macro="context/ui/widgets/show/macros/field"/>
</tal:field>
</tal:other>
</metal:field>
<tal:comment replace="nothing">Show query results as a list.</tal:comment>
<table metal:define-macro="list" class="list" width="100%"
tal:define="showHeaders showHeaders|python:True">
<tal:comment replace="nothing">Headers, with filters and sort arrows</tal:comment>
<tr tal:condition="showHeaders">
<tal:header repeat="column columns">
<th tal:define="widget column/field;
sortable python: tool.isSortable(widget['name'], className, 'search');
filterable widget/filterable|nothing"
tal:attributes="width column/width; align column/align">
<span tal:replace="structure python: tool.truncateText(_(widget['labelId']))"/>
<metal:icons use-macro="context/ui/navigate/macros/sortAndFilter"/>
<metal:details use-macro="context/ui/navigate/macros/showDetails"/>
</th>
</tal:header>
</tr>
<tal:comment replace="nothing">Results</tal:comment>
<tal:row repeat="obj objs">
<tr id="query_row" valign="top"
tal:define="odd repeat/obj/odd;
global currentNumber python: currentNumber + 1"
tal:attributes="class python:test(odd, 'even', 'odd')">
<tal:fields repeat="column columns">
<td tal:define="widget column/field"
tal:attributes="id python:'field_%s' % widget['name'];
width column/width; align column/align">
<metal:f use-macro="context/ui/result/macros/field"/>
</td>
</tal:fields>
</tr>
</tal:row>
</table>
<tal:comment replace="nothing">Show query results as a grid.</tal:comment>
<table metal:define-macro="grid" width="100%"
tal:define="modeElems python: resultMode.split('_');
cols python: (len(modeElems)==2) and int(modeElems[1]) or 4;
rows python: tool.splitList(objs, cols)">
<tr tal:repeat="row rows" valign="middle">
<td tal:repeat="obj row" tal:attributes="width python: '%d%%'%(100/cols)"
align="center" style="padding-top: 25px">
<tal:def define="global currentNumber python: currentNumber + 1">
<tal:col repeat="column columns">
<tal:field define="widget column/field">
<metal:f use-macro="context/ui/result/macros/field"/>
</tal:field>
</tal:col>
</tal:def>
</td>
</tr>
</table>
<tal:comment replace="nothing">Show paginated query results as a list or grid.</tal:comment>
<div id="queryResult" metal:define-macro="queryResult"
tal:define="_ python: tool.translate;
className request/className;
refInfo tool/getRefInfo;
refObject python: refInfo[0];
refField python: refInfo[1];
refUrlPart python: refObject and ('&ref=%s:%s' % (refObject.UID(), refField)) or '';
startNumber request/startNumber|python:'0';
startNumber python: int(startNumber);
searchName request/search|python:'';
searchDescr python: tool.getSearch(className, searchName, descr=True);
sortKey request/sortKey| python:'';
sortOrder request/sortOrder| python:'asc';
filterKey request/filterKey| python:'';
filterValue request/filterValue | python:'';
queryResult python: tool.executeQuery(className, search=searchDescr['search'], startNumber=startNumber, remember=True, sortBy=sortKey, sortOrder=sortOrder, filterKey=filterKey, filterValue=filterValue, refObject=refObject, refField=refField);
objs queryResult/objects;
totalNumber queryResult/totalNumber;
batchSize queryResult/batchSize;
ajaxHookId python:'queryResult';
navBaseCall python: 'askQueryResult(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, tool.absolute_url(), className, searchName);
newSearchUrl python: '%s/ui/search?className=%s%s' % (tool.absolute_url(), className, refUrlPart);
showSubTitles python: request.get('showSubTitles', 'true') == 'true';
resultMode python: tool.getResultMode(className);
showNewSearch showNewSearch|python:True;
enableLinks enableLinks|python: True">
<tal:result condition="objs">
<tal:comment replace="nothing">Display here POD templates if required.</tal:comment>
<table tal:define="widgets python: tool.getResultPodFields(className);
layoutType python:'view'"
tal:condition="python: objs and widgets"
tal:attributes="align dright">
<tr>
<td tal:define="contextObj python: objs[0]" tal:repeat="widget widgets">
<metal:pod use-macro="context/ui/widgets/show/macros/field"/>&nbsp;&nbsp;&nbsp;
</td>
</tr>
</table>
<tal:comment replace="nothing">The title of the search.</tal:comment>
<p>
<span tal:replace="structure searchDescr/translated"/>
(<span tal:replace="totalNumber"/>)
<tal:newSearch condition="python: showNewSearch and (searchName == 'customSearch')">
&nbsp;&mdash;&nbsp;<i><a tal:attributes="href newSearchUrl"
tal:content="python: _('search_new')"></a></i>
</tal:newSearch>
</p>
<table width="100%">
<tr>
<tal:comment replace="nothing">Search description</tal:comment>
<td tal:condition="searchDescr/translatedDescr">
<span class="discreet" tal:content="searchDescr/translatedDescr"></span><br/>
</td>
<td tal:attributes="align dright" width="25%">
<tal:comment replace="nothing">Appy (top) navigation</tal:comment>
<metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/>
</td>
</tr>
</table>
<tal:comment replace="nothing">Results, as a list or grid</tal:comment>
<tal:res define="columnLayouts python: tool.getResultColumnsLayouts(className, refInfo);
columns python: objs[0].getColumnsSpecifiers(columnLayouts, dir);
global currentNumber python: 0">
<tal:asList condition="python: resultMode == 'list'">
<metal:list use-macro="context/ui/result/macros/list"/>
</tal:asList>
<tal:asGrid condition="python: resultMode != 'list'">
<metal:grid use-macro="context/ui/result/macros/grid"/>
</tal:asGrid>
</tal:res>
<tal:comment replace="nothing">Appy (bottom) navigation</tal:comment>
<metal:nav use-macro="here/ui/navigate/macros/appyNavigate"/>
</tal:result>
<tal:noResult condition="not: objs">
<span tal:replace="python: _('query_no_result')"/>
<tal:newSearch condition="python: showNewSearch and (searchName == 'customSearch')">
<br/><i class="discreet"><a tal:attributes="href newSearchUrl"
tal:content="python: _('search_new')"></a></i>
</tal:newSearch>
</tal:noResult>
</div>

View file

@ -1,54 +0,0 @@
<tal:main define="tool python: context.config">
<html metal:use-macro="context/ui/template/macros/main">
<metal:fill fill-slot="content"
tal:define="className request/className;
refInfo request/ref|nothing;
searchInfo python: tool.getSearchInfo(className, refInfo);
cssJs python: {};
dummy python: tool.getCssJs(searchInfo['fields'], 'edit', cssJs)">
<tal:comment replace="nothing">Include type-specific CSS and JS.</tal:comment>
<link tal:repeat="cssFile cssJs/css" rel="stylesheet" type="text/css"
tal:attributes="href string:$appUrl/ui/$cssFile"/>
<script tal:repeat="jsFile cssJs/js" type="text/javascript"
tal:attributes="src string:$appUrl/ui/$jsFile"></script>
<tal:comment replace="nothing">Search title</tal:comment>
<h1><span tal:replace="python: _('%s_plural' % className)"/> —
<span tal:replace="python: _('search_title')"/></h1><br/>
<tal:comment replace="nothing">Form for searching objects of request/className.</tal:comment>
<form name="search" tal:attributes="action python: tool.absolute_url()+'/do'" method="post">
<input type="hidden" name="action" value="SearchObjects"/>
<input type="hidden" name="className" tal:attributes="value className"/>
<input tal:condition="refInfo" type="hidden" name="ref" tal:attributes="value refInfo"/>
<table width="100%">
<tr tal:repeat="searchRow python: tool.getGroupedSearchFields(searchInfo)"
valign="top">
<tal:widgets repeat="widget searchRow">
<td tal:define="scolspan widget/scolspan|python: 1"
tal:attributes="width python:'%d%%' % ((100/searchInfo['nbOfColumns'])*scolspan);
colspan scolspan">
<tal:field condition="widget">
<tal:show define="name widget/name;
widgetName python: 'w_%s' % name;
macroPage python: widget['type'].lower()">
<metal:call use-macro="python: getattr(appFolder.ui.widgets, macroPage).macros['search']"/>
</tal:show>
</tal:field><br class="discreet"/>
</td>
</tal:widgets>
</tr>
</table>
<tal:comment replace="nothing">Submit button</tal:comment>
<p tal:attributes="align dright"><br/>
<input type="submit" class="button"
tal:attributes="value python: _('search_button');
style string: background-image: url($appUrl/ui/buttonSearch.png);"/>
</p>
</form>
</metal:fill>
</html>
</tal:main>

View file

@ -1,212 +0,0 @@
<metal:main define-macro="main">
<tal:doctype tal:replace="structure string:&lt;!DOCTYPE html PUBLIC
&quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;" />
<html tal:define="user tool/getUser;
isAnon python: user.login == 'anon';
app tool/getApp;
appUrl app/absolute_url;
appFolder app/data;
appName tool/getAppName;
_ python: tool.translate;
req python: request;
resp req/RESPONSE;
lang tool/getUserLanguage;
layoutType tool/getLayoutType;
contextObj python: tool.getPublishedObject(layoutType) or tool.getHomeObject();
showPortlet python: tool.showPortlet(context, layoutType);
dir python: tool.getLanguageDirection(lang);
discreetLogin python: tool.getAttr('discreetLogin', source='app');
dleft python: (dir == 'ltr') and 'left' or 'right';
dright python: (dir == 'ltr') and 'right' or 'left';
x python: resp.setHeader('Content-type', 'text/html;;charset=UTF-8');
x python: resp.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:00 GMT+2');
x python: resp.setHeader('Content-Language', lang)"
tal:attributes="dir python: tool.getLanguageDirection(lang)">
<head>
<title tal:content="python: _('app_name')"></title>
<link rel="icon" type="image/x-icon" href="/favicon.ico"/>
<tal:link repeat="name tool/getGlobalCssJs">
<link tal:condition="python: name.endswith('.css') and not ((dir == 'ltr') and (name == 'appyrtl.css'))"
rel="stylesheet" type="text/css" tal:attributes="href string:$appUrl/ui/$name"/>
<script tal:condition="python: name.endswith('.js')" type="text/javascript"
tal:attributes="src string:$appUrl/ui/$name"></script>
</tal:link>
</head>
<body tal:on-error="structure python: tool.manageError(error)">
<tal:comment replace="nothing">Google Analytics stuff, if enabled</tal:comment>
<script tal:define="gaCode tool/getGoogleAnalyticsCode" tal:condition="gaCode"
type="text/javascript" tal:content="gaCode"></script>
<tal:comment replace="nothing">Grey background shown when popups are shown</tal:comment>
<div id="grey" class="grey"></div>
<tal:comment replace="nothing">Popup for confirming an action</tal:comment>
<div id="confirmActionPopup" class="popup">
<form id="confirmActionForm" method="post">
<div align="center">
<p id="appyConfirmText"></p>
<input type="hidden" name="actionType"/>
<input type="hidden" name="action"/>
<div id="commentArea" tal:attributes="align dleft"><br/>
<span tal:content="python: _('workflow_comment')" class="discreet"></span>
<textarea name="comment" cols="30" rows="3"></textarea>
<br/>
</div>
<br/>
<input type="button" onClick="doConfirm()"
tal:attributes="value python:_('yes')"/>
<input type="button" value="No" onClick="closePopup('confirmActionPopup')"
tal:attributes="value python:_('no')"/>
</div>
</form>
</div>
<tal:comment replace="nothing">Popup for reinitializing the password</tal:comment>
<div id="askPasswordReinitPopup" class="popup" tal:condition="python: isAnon and tool.showForgotPassword()">
<form id="askPasswordReinitForm" method="post"
tal:attributes="action python: tool.absolute_url() + '/askPasswordReinit'">
<div align="center">
<p tal:content="python: _('app_login')"></p>
<input type="text" size="35" name="login" id="login" value=""/>
<br/><br/>
<input type="button" onClick="doAskPasswordReinit()"
tal:attributes="value python:_('ask_password_reinit')"/>
<input type="button" value="No" onClick="closePopup('askPasswordReinitPopup')"
tal:attributes="value python:_('object_cancel')"/>
</div>
</form>
</div>
<table class="main" align="center" cellpadding="0">
<tal:comment replace="nothing">Top banner</tal:comment>
<tr class="top" metal:define-slot="top">
<td tal:define="bannerName python: (dir == 'ltr') and 'banner' or 'bannerrtl'"
tal:attributes="style python: 'background-image: url(%s/ui/%s.jpg)' % (appUrl, bannerName)">
<tal:comment replace="nothing">Top links</tal:comment>
<div style="margin-top: 4px"
tal:define="pages tool/getMainPages" tal:attributes="align dright">
<tal:comment replace="nothing">Icon "home"</tal:comment>
<a class="pageLink" tal:attributes="href appUrl; title python: _('app_home')">
<img tal:attributes="src string: $appUrl/ui/home.gif" style="margin-right: 3px"/>
</a>
<tal:comment replace="nothing">Additional links (or icons) from icons.pt</tal:comment>
<metal:call use-macro="app/ui/icons/macros/links"/>
<tal:comment replace="nothing">Top-level pages</tal:comment>
<a tal:repeat="page pages" class="pageLink"
tal:content="page/title" tal:attributes="href page/absolute_url"></a>
<tal:comment replace="nothing">Connect link if discreet login</tal:comment>
<a id="loginLink" name="loginLink" onclick="showLoginForm()" class="pageLink" style="cursor:pointer"
tal:condition="python: isAnon and discreetLogin" tal:content="python: _('app_connect')">
</a>
<tal:comment replace="nothing">Language selector</tal:comment>
<tal:lg condition="tool/showLanguageSelector">
<select class="pageLink"
tal:define="languages tool/getLanguages;
defaultLanguage python: languages[0]"
tal:attributes="onchange string:window.location='$appUrl/config/changeLanguage?language=' + this.options[this.selectedIndex].value">
<option tal:repeat="lg languages"
tal:content="python: tool.getLanguageName(lg)"
tal:attributes="selected python:lang == lg; value lg">
</option>
</select>
</tal:lg>
</div>
</td>
</tr>
<tal:comment replace="nothing">The message strip</tal:comment>
<tr valign="top">
<td>
<div style="position: relative">
<metal:msg use-macro="app/ui/page/macros/message"/>
</div>
</td>
</tr>
<tal:comment replace="nothing">The user strip</tal:comment>
<tr>
<td>
<table class="userStrip" width="100%">
<tr>
<tal:comment replace="nothing">The user login form for anonymous users</tal:comment>
<td align="center"
tal:condition="python: isAnon and ('/temp_folder/' not in req['ACTUAL_URL'])">
<form id="loginForm" name="loginForm" method="post" class="login"
tal:attributes="action python: tool.absolute_url() + '/performLogin'">
<input type="hidden" name="js_enabled" id="js_enabled" value="0"/>
<input type="hidden" name="cookies_enabled" id="cookies_enabled" value=""/>
<input type="hidden" name="login_name" id="login_name" value=""/>
<input type="hidden" name="pwd_empty" id="pwd_empty" value="0"/>
<tal:comment replace="nothing">The login fields, directly shown or not (depends on discreetLogin)</tal:comment>
<span id="loginFields" name="loginFields"
tal:attributes="style python: discreetLogin and 'display:none' or 'display:block'">
<span class="userStripText" tal:content="python: _('app_login')"/>
<input type="text" name="__ac_name" id="__ac_name" value="" style="width: 142px"/>&nbsp;
<span class="userStripText" tal:content="python: _('app_password')"/>
<input type="password" name="__ac_password" id="__ac_password" style="width: 142px"/>
<input type="submit" name="submit" onclick="setLoginVars()"
tal:define="label python: _('app_connect')" tal:attributes="value label; alt label"/>
<tal:comment replace="nothing">Forgot password?</tal:comment>
<a class="lostPassword" href="javascript: openPopup('askPasswordReinitPopup')"
tal:condition="tool/showForgotPassword"
tal:content="python: _('forgot_password')">
</a>
</span>
</form>
</td>
<tal:comment replace="nothing">User info and controls for authenticated users</tal:comment>
<td tal:condition="not: isAnon">
<table class="buttons" width="99%">
<tr>
<td>
<tal:comment replace="nothing">Config</tal:comment>
<a tal:condition="python: user.has_role('Manager')"
tal:attributes="href python: tool.getUrl(nav='');
title python: _('%sTool' % appName)">
<img tal:attributes="src string:$appUrl/ui/appyConfig.gif"/>
</a>
<tal:comment replace="nothing">Additional icons from icons.pt</tal:comment>
<metal:call use-macro="app/ui/icons/macros/icons"/>
<tal:comment replace="nothing">Log out</tal:comment>
<a tal:attributes="href python: tool.absolute_url() + '/performLogout';
title python: _('app_logout')">
<img tal:attributes="src string: $appUrl/ui/logout.gif"/>
</a>
</td>
<td class="userStripText" tal:define="userInfo tool/getUserLine" tal:attributes="align dright">
<span tal:content="python: userInfo[0]"></span>
<a tal:condition="python: userInfo[1]"
tal:attributes="href python: userInfo[1]">
<img tal:attributes="src string: $appUrl/ui/edit.png"/>
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tal:comment replace="nothing">The navigation strip</tal:comment>
<tr tal:condition="python: contextObj and showPortlet and (layoutType != 'edit')">
<td><metal:navigate use-macro="app/ui/navigate/macros/navigationStrip"/></td>
</tr>
<tr>
<td>
<table width="100%" cellpadding="0" cellspacing="0">
<tr valign="top">
<tal:comment replace="nothing">Portlet</tal:comment>
<td tal:condition="showPortlet" class="portlet">
<metal:portlet use-macro="app/ui/portlet/macros/portlet"/>
</td>
<tal:comment replace="nothing">Page content</tal:comment>
<td class="content"><span metal:define-slot="content"></span></td>
</tr>
</table>
</td>
</tr>
<tr><tal:comment replace="nothing">Footer</tal:comment>
<td><metal:call use-macro="app/ui/footer/macros/footer"/></td>
</tr>
</table>
</body>
</html>
</metal:main>

View file

@ -1,20 +0,0 @@
<tal:main define="tool context/config">
<html metal:use-macro="context/ui/template/macros/main">
<metal:fill fill-slot="content"
tal:define="dummy python: contextObj.allows('View', raiseError=True);
errors python: req.get('errors', {});
layout python: contextObj.getPageLayout(layoutType);
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
phase phaseInfo/name;
cssJs python: {};
page req/page|python:contextObj.getDefaultViewPage();
dummy python: contextObj.removeMyLock(user, page);
groupedWidgets python: contextObj.getGroupedAppyTypes(layoutType, page, cssJs=cssJs);"
tal:on-error="structure python: tool.manageError(error)">
<metal:prologue use-macro="context/ui/page/macros/prologue"/>
<metal:show use-macro="context/ui/page/macros/show"/>
<metal:footer use-macro="context/ui/page/macros/footer"/>
</metal:fill>
</html>
</tal:main>

View file

@ -1,34 +0,0 @@
<tal:comment replace="nothing">View macro for an Action.</tal:comment>
<metal:view define-macro="view">
<form name="executeAppyAction"
tal:define="formId python: '%s_%s_form' % (contextObj.UID(), name);
label python: contextObj.translate(widget['labelId'])"
tal:attributes="id formId; action python: tool.absolute_url()+'/do'">
<input type="hidden" name="action" value="ExecuteAppyAction"/>
<input type="hidden" name="objectUid" tal:attributes="value contextObj/UID"/>
<input type="hidden" name="fieldName" tal:attributes="value name"/>
<tal:confirm condition="widget/confirm">
<input type="button" class="button"
tal:define="labelConfirm python: contextObj.translate(widget['labelId'] + '_confirm')"
tal:attributes="value python: tool.truncateValue(label);
title label;
style string: background-image: url($appUrl/ui/buttonAction.png);
onClick python: 'askConfirm(\'form\', \'%s\', &quot;%s&quot;)' % (formId, labelConfirm)"/>
</tal:confirm>
<input type="submit" class="button" name="do" tal:condition="not: widget/confirm"
tal:attributes="value python: tool.truncateValue(label);
title label;
style string: background-image: url($appUrl/ui/buttonAction.png);"/>
</form>
</metal:view>
<tal:comment replace="nothing">Edit macro for an Action.</tal:comment>
<metal:edit define-macro="edit"></metal:edit>
<tal:comment replace="nothing">Cell macro for an Action.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/action/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for an Action.</tal:comment>
<metal:search define-macro="search"></metal:search>

View file

@ -1,42 +0,0 @@
<tal:comment replace="nothing">View macro for a Boolean.</tal:comment>
<metal:view define-macro="view">
<span tal:replace="value"></span>
<input type="hidden" tal:condition="masterCss"
tal:attributes="class masterCss; value rawValue; name name; id name"/>
</metal:view>
<tal:comment replace="nothing">Edit macro for an Boolean.</tal:comment>
<metal:edit define-macro="edit">
<input type="checkbox"
tal:attributes="name python: name + '_visible'; id name;
checked python:contextObj.checkboxChecked(name, rawValue);
onClick python:'toggleCheckbox(\'%s\', \'%s_hidden\');;updateSlaves(this)' % (name, name);
class masterCss"/>
<input type="hidden"
tal:attributes="name name;
id string:${name}_hidden;
value python: test(contextObj.checkboxChecked(name, rawValue), 'True', 'False')"/>
</metal:edit>
<tal:comment replace="nothing">Cell macro for an Boolean.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/boolean/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for an Boolean.</tal:comment>
<metal:search define-macro="search"
tal:define="typedWidget python:'%s*bool' % widgetName">
<label tal:attributes="for widgetName" tal:content="python: _(widget['labelId'])"></label><br>&nbsp;&nbsp;
<tal:yes define="valueId python:'%s_yes' % name">
<input type="radio" value="True" tal:attributes="name typedWidget; id valueId"/>
<label tal:attributes="for valueId" tal:content="python: _('yes')"></label>
</tal:yes>
<tal:no define="valueId python:'%s_no' % name">
<input type="radio" value="False" tal:attributes="name typedWidget; id valueId"/>
<label tal:attributes="for valueId" tal:content="python: _('no')"></label>
</tal:no>
<tal:whatever define="valueId python:'%s_whatever' % name">
<input type="radio" value="" tal:attributes="name typedWidget; id valueId" checked="checked"/>
<label tal:attributes="for valueId" tal:content="python: _('whatever')"></label>
</tal:whatever><br/>
</metal:search>

View file

@ -1,210 +0,0 @@
<tal:comment replace="nothing">Month view macro</tal:comment>
<div metal:define-macro="viewMonth"
tal:define="fieldName request/fieldName;
ajaxHookId python: contextObj.UID() + fieldName;
month request/month;
monthDayOne python: DateTime('%s/01' % month);
today python: DateTime('00:00');
grid python: contextObj.callField(fieldName, 'getMonthGrid', month);
allEventTypes python: contextObj.callField(fieldName, 'getEventTypes', contextObj);
preComputed python: contextObj.callField(fieldName, 'getPreComputedInfo', contextObj, monthDayOne, grid);
defaultDate python: contextObj.callField(fieldName, 'getDefaultDate', contextObj);
defaultDateMonth python: defaultDate.strftime('%Y/%m');
previousMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'previous');
nextMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'next');
widget python: contextObj.getAppyType(fieldName, asDict=True);
mayEdit python: contextObj.allows(widget['writePermission']);
objUrl contextObj/absolute_url;
startDate python: contextObj.callField(fieldName, 'getStartDate', contextObj);
endDate python: contextObj.callField(fieldName, 'getEndDate', contextObj);
otherCalendars python: contextObj.callField(fieldName, 'getOtherCalendars', contextObj, preComputed);"
tal:attributes="id ajaxHookId">
<script type="text/javascript"
tal:content="python: 'var %s_maxEventLength = %d;' % (fieldName, widget['maxEventLength'])">
</script>
<tal:comment replace="nothing">Month chooser</tal:comment>
<div style="margin-bottom: 5px"
tal:define="fmt python: '%Y/%m/%d';
goBack python: not startDate or (startDate.strftime(fmt) &lt; grid[0][0].strftime(fmt));
goForward python: not endDate or (endDate.strftime(fmt) &gt; grid[-1][-1].strftime(fmt))">
<tal:comment replace="nothing">Go to the previous month</tal:comment>
<img style="cursor:pointer" tal:condition="goBack"
tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png;
onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,previousMonth)"/>
<tal:comment replace="nothing">Go back to the default date</tal:comment>
<tal:button condition="python: goBack or goForward">
<input type="button"
tal:define="fmt python: '%Y/%m';
label python: test(defaultDate.strftime(fmt) == today.strftime(fmt), 'today', 'goto_source')"
tal:attributes="value python: _(label);
onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,defaultDateMonth);
disabled python: defaultDate.strftime(fmt) == monthDayOne.strftime(fmt)"/>
</tal:button>
<tal:comment replace="nothing">Go to the next month</tal:comment>
<img style="cursor:pointer" tal:condition="goForward"
tal:attributes="src string: $appUrl/ui/arrowRightSimple.png;
onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,nextMonth)"/>
<span tal:content="python: _('month_%s' % monthDayOne.aMonth())"></span>
<span tal:content="python: month.split('/')[0]"></span>
</div>
<tal:comment replace="nothing">Calendar month view</tal:comment>
<table cellpadding="0" cellspacing="0" width="100%" class="list" style="font-size: 95%"
tal:define="rowHeight python: int(widget['height']/float(len(grid)))">
<tal:comment replace="nothing">1st row: names of days</tal:comment>
<tr height="22px">
<th tal:repeat="dayName python: contextObj.callField(fieldName, 'getNamesOfDays', contextObj)"
tal:content="dayName" width="14%">
</th>
</tr>
<tal:comment replace="nothing">The calendar in itself</tal:comment>
<tr tal:repeat="row grid" valign="top" tal:attributes="height rowHeight">
<tal:cell repeat="date row">
<tal:cel define="tooEarly python: startDate and (date &lt; startDate);
tooLate python: endDate and not tooEarly and (date &gt; endDate);
inRange python: not tooEarly and not tooLate;
cssClasses python: contextObj.callField(fieldName, 'getCellStyle', contextObj, date, today)">
<tal:comment replace="nothing">Dump an empty cell if we are out of the supported date range</tal:comment>
<td tal:condition="not: inRange" tal:attributes="class cssClasses">
</td>
<tal:comment replace="nothing">Dump a normal cell if we are in range</tal:comment>
<tal:td condition="inRange">
<td tal:define="events python: contextObj.callField(fieldName, 'getEventsAt', contextObj, date);
spansDays python: contextObj.callField(fieldName, 'hasEventsAt', contextObj, date+1, events);
mayCreate python: mayEdit and not events;
mayDelete python: mayEdit and events;"
tal:attributes="style python: test(date.isCurrentDay(), 'font-weight:bold', 'font-weight:normal');
class cssClasses;
onmouseover python: test(mayEdit, 'this.getElementsByTagName(\'img\')[0].style.visibility=\'visible\'', '');
onmouseout python: test(mayEdit, 'this.getElementsByTagName(\'img\')[0].style.visibility=\'hidden\'', '')">
<tal:day define="day date/day;
dayString python: date.strftime('%Y/%m/%d')">
<span tal:content="day"></span>
<span tal:condition="python: day == 1"
tal:content="python: _('month_%s_short' % date.aMonth())"></span>
<tal:comment replace="nothing">Icon for adding an event</tal:comment>
<tal:create condition="mayCreate">
<img style="visibility:hidden; cursor:pointer"
tal:define="info python: contextObj.callField(fieldName, 'getApplicableEventsTypesAt', contextObj, date, allEventTypes, preComputed, True)"
tal:condition="info/eventTypes"
tal:attributes="src string: $appUrl/ui/plus.png;
onclick python: 'openEventPopup(\'new\',\'%s\',\'%s\',null,\'%s\',\'%s\')' % (fieldName, dayString, info['eventTypes'], info['message'])"/>
</tal:create>
<tal:comment replace="nothing">Icon for deleting an event</tal:comment>
<img tal:condition="mayDelete" style="visibility:hidden; cursor:pointer"
tal:attributes="src string: $appUrl/ui/delete.png;
onclick python: 'openEventPopup(\'del\',\'%s\',\'%s\',\'%s\',null,null)' % (fieldName, dayString, str(spansDays))"/>
<tal:events condition="events">
<tal:comment replace="nothing">A single event is allowed for the moment</tal:comment>
<div tal:define="eventType python: events[0]['eventType']">
<span style="color: grey"
tal:content="python: contextObj.callField(fieldName, 'getEventName', contextObj, eventType)"></span>
</div>
</tal:events>
<tal:comment replace="nothing">Events from other calendars</tal:comment>
<tal:others condition="otherCalendars">
<tal:e define="otherEvents python: contextObj.callField(fieldName,'getOtherEventsAt',contextObj,date,otherCalendars)"
condition="otherEvents">
<div tal:repeat="event otherEvents" tal:content="event/name"
tal:attributes="style python: 'color: %s;; font-style: italic' % event['color']"></div>
</tal:e>
</tal:others>
<tal:comment replace="nothing">Additional info</tal:comment>
<tal:info define="info python: contextObj.callField(fieldName,'getAdditionalInfoAt', contextObj, date, preComputed)"
condition="info" replace="structure info"/>
</tal:day>
</td>
</tal:td>
</tal:cel>
</tal:cell>
</tr>
</table>
<tal:comment replace="nothing">Popup for creating a calendar event</tal:comment>
<div tal:define="prefix python: '%s_newEvent' % fieldName;
popupId python: prefix + 'Popup'"
tal:attributes="id popupId" class="popup" align="center">
<form tal:attributes="id python: prefix + 'Form'" method="post">
<input type="hidden" name="fieldName" tal:attributes="value fieldName"/>
<input type="hidden" name="month" tal:attributes="value month"/>
<input type="hidden" name="name" tal:attributes="value fieldName"/>
<input type="hidden" name="action" value="Process"/>
<input type="hidden" name="actionType" value="createEvent"/>
<input type="hidden" name="day"/>
<tal:comment replace="nothing">Choose an event type</tal:comment>
<div align="center" style="margin-bottom: 3px" tal:content="python: _('which_event')"></div>
<select name="eventType">
<option value="" tal:content="python: _('choose_a_value')"></option>
<option tal:repeat="eventType allEventTypes"
tal:content="python: contextObj.callField(fieldName, 'getEventName', contextObj, eventType)"
tal:attributes="value eventType">
</option>
</select><br/><br/>
<tal:comment replace="nothing">Span the event on several days</tal:comment>
<div align="center" class="discreet" style="margin-bottom: 3px">
<span tal:content="python: _('event_span')"></span>
<input type="text" size="3" name="eventSpan"/>
</div>
<input type="button"
tal:attributes="value python:_('object_save');
onClick python: 'triggerCalendarEvent(\'new\',\'%s\',\'%s\',\'%s\',%s_maxEventLength)' % (ajaxHookId,fieldName,objUrl,fieldName)"/>
<input type="button"
tal:attributes="value python:_('object_cancel');
onclick python: 'closePopup(\'%s\')' % popupId"/>
</form>
</div>
<tal:comment replace="nothing">Popup for deleting a calendar event</tal:comment>
<div tal:define="prefix python: '%s_delEvent' % fieldName;
popupId python: prefix + 'Popup'"
tal:attributes="id popupId" class="popup" align="center">
<form tal:attributes="id python: prefix + 'Form'" method="post">
<input type="hidden" name="fieldName" tal:attributes="value fieldName"/>
<input type="hidden" name="month" tal:attributes="value month"/>
<input type="hidden" name="name" tal:attributes="value fieldName"/>
<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"
tal:content="python: _('delete_confirm')"></div>
<tal:comment replace="nothing">Delete successive events?</tal:comment>
<div class="discreet" style="margin-bottom: 10px"
tal:attributes="id python: prefix + 'DelNextEvent'">
<input type="checkbox" name="deleteNext_cb"
tal:attributes="id python: prefix + '_cb';
onClick python:'toggleCheckbox(\'%s_cb\', \'%s_hd\')' % (prefix, prefix);"/>
<input type="hidden" tal:attributes="id python: prefix + '_hd'" name="deleteNext"/>
<span tal:content="python: _('del_next_events')"/>
</div>
<input type="button"
tal:attributes="value python:_('yes');
onClick python: 'triggerCalendarEvent(\'del\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,fieldName,objUrl)"/>
<input type="button"
tal:attributes="value python:_('no');
onclick python: 'closePopup(\'%s\')' % popupId"/>
</form>
</div>
</div>
<tal:comment replace="nothing">View macro</tal:comment>
<metal:view define-macro="view"
tal:define="defaultDate python: contextObj.callField(widget['name'], 'getDefaultDate', contextObj);
dummy python: request.set('fieldName', widget['name']);
dummy python: request.set('month', defaultDate.strftime('%Y/%m'))">
<metal:call use-macro="app/ui/widgets/calendar/macros/viewMonth"/>
</metal:view>
<tal:comment replace="nothing">Edit macro</tal:comment>
<metal:edit define-macro="edit"></metal:edit>
<tal:comment replace="nothing">Cell macro</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/calendar/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro</tal:comment>
<metal:search define-macro="search"></metal:search>

View file

@ -1,43 +0,0 @@
<tal:comment replace="nothing">View macro for a Computed.</tal:comment>
<metal:view define-macro="view">
<tal:sync condition="sync">
<span tal:condition="widget/plainText" tal:replace="value"/>
<span tal:condition="not: widget/plainText" tal:replace="structure value"/>
</tal:sync>
<tal:async condition="not: sync">
<div tal:define= "ajaxHookId python: contextObj.UID() + name"
tal:attributes = "id ajaxHookId">
<script type="text/javascript"
tal:content="python: 'askComputedField(\'%s\',\'%s\',\'%s\')' % (ajaxHookId, contextObj.absolute_url(), name)">
</script>
</div>
</tal:async>
</metal:view>
<tal:comment replace="nothing">Ajax-called view content of a non sync Computed field.</tal:comment>
<metal:view define-macro="viewContent"
tal:define="name request/fieldName;
widget python: contextObj.getAppyType(name, asDict=True);
value python: contextObj.getFieldValue(name);
sync python:True">
<metal:call use-macro="app/ui/widgets/computed/macros/view"/>
</metal:view>
<tal:comment replace="nothing">Edit macro for a Computed.</tal:comment>
<metal:edit define-macro="edit">
<metal:call use-macro="app/ui/widgets/computed/macros/view"/>
</metal:edit>
<tal:comment replace="nothing">Cell macro for a Computed.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/computed/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for a Computed.</tal:comment>
<metal:search define-macro="search">
<label tal:attributes="for widgetName" tal:content="python: _(widget['labelId'])"></label><br>&nbsp;&nbsp;
<input type="text" tal:define="maxChars python: test(widget['maxChars'], widget['maxChars'], '')"
tal:attributes="name python: '%s*string' % widgetName;
maxlength maxChars; size widget/width;
value widget/sdefault"/>
</metal:search>

View file

@ -1,153 +0,0 @@
<tal:comment replace="nothing">View macro for a Date.</tal:comment>
<metal:view define-macro="view"><span tal:replace="value"/></metal:view>
<tal:comment replace="nothing">Edit macro for an Date.</tal:comment>
<metal:edit define-macro="edit"
tal:define="years python: contextObj.getSelectableYears(widget['name'])">
<tal:comment replace="nothing">Day</tal:comment>
<select tal:define="days python:range(1,32)"
tal:attributes="name string:${name}_day;
id string:${name}_day;">
<option value="">-</option>
<tal:days repeat="day days">
<option tal:define="zDay python: str(day).zfill(2)"
tal:attributes="value zDay;
selected python:contextObj.dateValueSelected(name, 'day', day, rawValue)"
tal:content="zDay"></option>
</tal:days>
</select>
<tal:comment replace="nothing">Month</tal:comment>
<select tal:define="months python:range(1,13)"
tal:attributes="name string:${name}_month;
id string:${name}_month;">
<option value="">-</option>
<tal:months repeat="month months">
<option tal:define="zMonth python: str(month).zfill(2)"
tal:attributes="value zMonth;
selected python:contextObj.dateValueSelected(name, 'month', month, rawValue)"
tal:content="zMonth"></option>
</tal:months>
</select>
<tal:comment replace="nothing">Year</tal:comment>
<select tal:attributes="name string:${name}_year;
id string:${name}_year;">
<option value="">-</option>
<option tal:repeat="year years"
tal:attributes="value year;
selected python:contextObj.dateValueSelected(name, 'year', year, rawValue)"
tal:content="year"></option>
</select>
<tal:comment replace="nothing">The icon for displaying the calendar popup</tal:comment>
<tal:calendar condition="widget/calendar">
<input type="hidden" tal:attributes="id name; name name"/>
<img tal:attributes="id string:${name}_img; src string: $appUrl/ui/calendar.gif"/>
<script type="text/javascript" tal:content="python: contextObj.getCalendarInit(name, years)"></script>
</tal:calendar>
<tal:hour condition="python: widget['format'] == 0">
<select tal:define="hours python:range(0,24);"
tal:attributes="name string:${name}_hour;
id string:${name}_hour;">
<option value="">-</option>
<tal:hours repeat="hour hours">
<option tal:define="zHour python: str(hour).zfill(2)"
tal:attributes="value zHour;
selected python:contextObj.dateValueSelected(name, 'hour', hour, rawValue)"
tal:content="zHour"></option>
</tal:hours>
</select> :
<select tal:define="minutes python:range(0,60,5);"
tal:attributes="name string:${name}_minute;
id string:${name}_minute;">
<option value="">-</option>
<tal:minutes repeat="minute minutes">
<option tal:define="zMinute python: str(minute).zfill(2)"
tal:attributes="value zMinute;
selected python:contextObj.dateValueSelected(name, 'minute', minute, rawValue)"
tal:content="zMinute"></option>
</tal:minutes>
</select>
</tal:hour>
</metal:edit>
<tal:comment replace="nothing">Cell macro for an Date.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/date/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for an Date.</tal:comment>
<metal:search define-macro="search"
tal:define="years python:range(widget['startYear'], widget['endYear']+1)">
<label tal:content="python: _(widget['labelId'])"></label>
<table>
<tal:comment replace="nothing">From</tal:comment>
<tr tal:define="fromName python: '%s_from' % name;
dayFromName python: '%s_from_day' % name;
monthFromName python: '%s_from_month' % name;
yearFromName python: '%s*date' % widgetName">
<td width="10px">&nbsp;</td>
<td>
<label tal:content="python: _('search_from')"></label>
</td>
<td>
<select tal:attributes="id dayFromName; name dayFromName">
<option value="">--</option>
<option tal:repeat="value python: [str(v).zfill(2) for v in range(1, 32)]"
tal:content="value" tal:attributes="value value"></option>
</select> /
<select tal:attributes="id monthFromName; name monthFromName">
<option value="">--</option>
<option tal:repeat="value python: [str(v).zfill(2) for v in range(1, 13)]"
tal:content="value" tal:attributes="value value"></option>
</select> /
<select tal:attributes="id yearFromName; name yearFromName">
<option value="">--</option>
<option tal:repeat="value python:range(widget['startYear'], widget['endYear']+1)"
tal:content="value" tal:attributes="value value"></option>
</select>
<tal:comment replace="nothing">The icon for displaying the calendar popup</tal:comment>
<tal:calendar condition="widget/calendar">
<input type="hidden" tal:attributes="id fromName; name fromName"/>
<img tal:attributes="id string:${fromName}_img; src string: $appUrl/ui/calendar.gif"/>
<script type="text/javascript" tal:content="python: tool.getCalendarInit(fromName, years)"></script>
</tal:calendar>
</td>
</tr>
<tal:comment replace="nothing">To</tal:comment>
<tr tal:define="toName python: '%s_to' % name;
dayToName python: '%s_to_day' % name;
monthToName python: '%s_to_month' % name;
yearToName python: '%s_to_year' % name">
<td></td>
<td>
<label tal:content="python: _('search_to')"></label>&nbsp;&nbsp;&nbsp;&nbsp;
</td>
<td height="20px;">
<select tal:attributes="id dayToName; name dayToName">
<option value="">--</option>
<option tal:repeat="value python: [str(v).zfill(2) for v in range(1, 32)]"
tal:content="value" tal:attributes="value value"></option>
</select> /
<select tal:attributes="id monthToName; name monthToName">
<option value="">--</option>
<option tal:repeat="value python: [str(v).zfill(2) for v in range(1, 13)]"
tal:content="value" tal:attributes="value value"></option>
</select> /
<select tal:attributes="id yearToName; name yearToName">
<option value="">--</option>
<option tal:repeat="value python:range(widget['startYear'], widget['endYear']+1)"
tal:content="value" tal:attributes="value value"></option>
</select>
<tal:comment replace="nothing">The icon for displaying the calendar popup</tal:comment>
<tal:calendar condition="widget/calendar">
<input type="hidden" tal:attributes="id toName; name toName"/>
<img tal:attributes="id string:${toName}_img; src string: $appUrl/ui/calendar.gif"/>
<script type="text/javascript" tal:content="python: tool.getCalendarInit(toName, years)"></script>
</tal:calendar>
</td>
</tr>
</table>
</metal:search>

View file

@ -1,70 +0,0 @@
<tal:comment replace="nothing">View macro for a File.</tal:comment>
<metal:view define-macro="view"
tal:define="info python: contextObj.getFileInfo(value);
empty not: info/size;
imageSrc string:${contextObj/absolute_url}/download?name=$name">
<tal:file condition="python: not empty and not widget['isImage']">
<a tal:attributes="href imageSrc"
tal:content="info/filename">
</a>&nbsp;&nbsp;-
<i class="discreet" tal:content="python:'%sKb' % (info['size'] / 1024)"></i>
</tal:file>
<tal:image condition="python: not empty and widget['isImage']">
<img tal:attributes="src python: imageSrc" />
</tal:image>
<tal:nothing tal:condition="empty">-</tal:nothing>
</metal:view>
<tal:comment replace="nothing">Edit macro for an File.</tal:comment>
<metal:edit define-macro="edit"
tal:define="info python: contextObj.getFileInfo(value);
empty not: info/size;">
<tal:showFile condition="not: empty">
<metal:call use-macro="app/ui/widgets/file/macros/view"/><br/>
</tal:showFile>
<tal:editButtons condition="not: empty">
<tal:comment replace="nothing">Keep the file unchanged.</tal:comment>
<input type="radio" value="nochange"
tal:attributes="checked python:test(info['size']!=0, 'checked', None);
name string:${name}_delete;
id string:${name}_nochange;
onclick string:document.getElementById('${name}_file').disabled=true;"/>
<label tal:attributes="for string:${name}_nochange">Keep the file unchanged</label>
<br/>
<tal:comment replace="nothing">Delete the file.</tal:comment>
<tal:delete condition="not: widget/required">
<input type="radio" value="delete"
tal:attributes="name string:${name}_delete;
id string:${name}_delete;
onclick string:document.getElementById('${name}_file').disabled=true;"/>
<label tal:attributes="for string:${name}_delete">Delete the file</label>
<br/>
</tal:delete>
<tal:comment replace="nothing">Replace with a new file.</tal:comment>
<input type="radio" value=""
tal:attributes="checked python:test(info['size']==0, 'checked', None);
name string:${name}_delete;
id string:${name}_upload;
onclick string:document.getElementById('${name}_file').disabled=false"/>
<label tal:attributes="for string:${name}_upload;">Replace it with a new file</label>
<br/>
</tal:editButtons>
<tal:comment replace="nothing">The upload field.</tal:comment>
<input type="file"
tal:attributes="name string:${name}_file;
id string:${name}_file;
size widget/width"/>
<script type="text/javascript"
tal:define="isDisabled python:test(empty, 'false', 'true')"
tal:content="string: document.getElementById('${name}_file').disabled=$isDisabled;">
</script>
</metal:edit>
<tal:comment replace="nothing">Cell macro for an File.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/file/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for an File.</tal:comment>
<metal:search define-macro="search"></metal:search>

View file

@ -1,38 +0,0 @@
<tal:comment replace="nothing">View macro for a Float.</tal:comment>
<metal:view define-macro="view">
<span tal:replace="value"></span>
<input type="hidden" tal:condition="masterCss"
tal:attributes="class masterCss; value value; name name; id name"/>
</metal:view>
<tal:comment replace="nothing">Edit macro for an Float.</tal:comment>
<metal:edit define-macro="edit">
<input tal:define="maxChars python: test(widget['maxChars'], widget['maxChars'], '')"
tal:attributes="id name; name name; size widget/width; maxlength maxChars;
value python: test(inRequest, requestValue, value)" type="text"/>
</metal:edit>
<tal:comment replace="nothing">Cell macro for an Float.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/float/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for an Float.</tal:comment>
<metal:search define-macro="search"
tal:define="maxChars python: test(widget['maxChars'], widget['maxChars'], '')">
<label tal:content="python: _(widget['labelId'])"></label><br>&nbsp;&nbsp;
<tal:from define="fromName python: '%s*float' % widgetName">
<label tal:attributes="for fromName" tal:content="python: _('search_from')"></label>
<input type="text"
tal:attributes="name fromName; maxlength maxChars;
value python: widget['sdefault'][0];
size widget/swidth"/>
</tal:from>
<tal:to define="toName python: '%s_to' % name">
<label tal:attributes="for toName" tal:content="python: _('search_to')"></label>
<input type="text"
tal:attributes="name toName; maxlength maxChars;
value python: widget['sdefault'][1];
size widget/swidth"/>
</tal:to><br/>
</metal:search>

View file

@ -1,11 +0,0 @@
<tal:comment replace="nothing">View macro for an Info.</tal:comment>
<metal:view define-macro="view"><tal:comment replace="nothing">Shows nothing more.</tal:comment></metal:view>
<tal:comment replace="nothing">Edit macro for an Info.</tal:comment>
<metal:edit define-macro="edit"></metal:edit>
<tal:comment replace="nothing">Cell macro for an Info.</tal:comment>
<metal:cell define-macro="cell"></metal:cell>
<tal:comment replace="nothing">Search macro for an Info.</tal:comment>
<metal:search define-macro="search"></metal:search>

View file

@ -1,38 +0,0 @@
<tal:comment replace="nothing">View macro for an Integer.</tal:comment>
<metal:view define-macro="view">
<span tal:replace="value"></span>
<input type="hidden" tal:condition="masterCss"
tal:attributes="class masterCss; value value; name name; id name"/>
</metal:view>
<tal:comment replace="nothing">Edit macro for an Integer.</tal:comment>
<metal:edit define-macro="edit">
<input tal:define="maxChars python: test(widget['maxChars'], widget['maxChars'], '')"
tal:attributes="id name; name name; size widget/width; maxlength maxChars;
value python: test(inRequest, requestValue, value)" type="text"/>
</metal:edit>
<tal:comment replace="nothing">Cell macro for an Integer.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/integer/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for an Integer.</tal:comment>
<metal:search define-macro="search"
tal:define="maxChars python: test(widget['maxChars'], widget['maxChars'], '')">
<label tal:content="python: _(widget['labelId'])"></label><br>&nbsp;&nbsp;
<tal:from define="fromName python: '%s*int' % widgetName">
<label tal:attributes="for fromName" tal:content="python: _('search_from')"></label>
<input type="text"
tal:attributes="name fromName; maxlength maxChars;
value python: widget['sdefault'][0];
size widget/swidth"/>
</tal:from>
<tal:to define="toName python: '%s_to' % name">
<label tal:attributes="for toName" tal:content="python: _('search_to')"></label>
<input type="text"
tal:attributes="name toName; maxlength maxChars;
value python: widget['sdefault'][1];
size widget/swidth"/>
</tal:to><br/>
</metal:search>

View file

@ -1,74 +0,0 @@
<tal:comment replace="nothing">Single row.</tal:comment>
<tr metal:define-macro="row" valign="top"
tal:attributes="style python: (rowIndex==-1) and 'display: none' or ''">
<td align="center" tal:repeat="fieldInfo widget/fieldsd">
<tal:show define="widget python: fieldInfo[1];
tagCss python: 'noStyle';
widgetName python: '%s*%d' % (widget['name'], rowIndex)">
<metal:call use-macro="app/ui/widgets/show/macros/field"/>
</tal:show>
</td>
<tal:comment replace="nothing">Icon for removing the row</tal:comment>
<td tal:condition="python: layoutType=='edit'"
tal:attributes="align dright">
<img style="cursor:pointer"
tal:attributes="src string:$appUrl/ui/delete.png;
title python: 'Delete';
onClick python: 'deleteRow(\'list_%s\',this)' % name"/>
</td>
</tr>
<tal:comment replace="nothing">The whole table, edit or view.</tal:comment>
<table metal:define-macro="table"
tal:define="isEdit python: layoutType == 'edit'"
tal:condition="python: isEdit or value"
tal:attributes="id python: 'list_%s' % name;
class python: isEdit and 'grid' or 'list'">
<tal:comment replace="nothing">Header</tal:comment>
<tr valign="bottom">
<th tal:repeat="fieldInfo widget/fieldsd"
tal:content="structure python: _(fieldInfo[1]['labelId'])">
</th>
<tal:comment replace="nothing">Icon for adding a new row.</tal:comment>
<th tal:condition="isEdit">
<img style="cursor:pointer"
tal:attributes="src string:$appUrl/ui/plus.png;
title python: _('add_ref');
onClick python: 'insertRow(\'list_%s\')' % name"/>
</th>
</tr>
<tal:comment replace="nothing">Template row (edit only)</tal:comment>
<tal:templateRow define="rowIndex python:-1" condition="isEdit">
<metal:call use-macro="app/ui/widgets/list/macros/row"/>
</tal:templateRow>
<tr height="7px" tal:condition="isEdit"><td></td></tr>
<tal:comment replace="nothing">Rows of data</tal:comment>
<tal:rows define="rows python: inRequest and requestValue or value"
repeat="row rows">
<tal:row define="rowIndex repeat/row/index">
<metal:call use-macro="app/ui/widgets/list/macros/row"/>
</tal:row>
</tal:rows>
</table>
<tal:comment replace="nothing">View</tal:comment>
<metal:view define-macro="view">
<metal:call use-macro="app/ui/widgets/list/macros/table"/>
</metal:view>
<tal:comment replace="nothing">Edit</tal:comment>
<metal:edit define-macro="edit">
<tal:comment replace="nothing">
The following input makes Appy aware that this field is in the request.
</tal:comment>
<input type="hidden" tal:attributes="name name" value="">
<metal:call use-macro="app/ui/widgets/list/macros/table"/>
</metal:edit>
<tal:comment replace="nothing">Cell</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/list/macros/table"/>
</metal:cell>
<tal:comment replace="nothing">Search</tal:comment>
<metal:search define-macro="search"></metal:search>

View file

@ -1,28 +0,0 @@
<tal:comment replace="nothing">View macro</tal:comment>
<metal:view define-macro="view">
<tal:comment replace="nothing">var "value" is misused and contains the contact params for Ogone.</tal:comment>
<tal:comment replace="nothing">The form for sending the payment request to Ogone.</tal:comment>
<p tal:content="value"></p>
<form method="post" id="form1" name="form1"
tal:define="env value/env"
tal:attributes="action string: https://secure.ogone.com/ncol/$env/orderstandard.asp">
<tal:fields repeat="item value/items">
<input type="hidden" tal:condition="python: item[0] != 'env'"
tal:attributes="id python: item[0]; name python: item[0]; value python: item[1]"/>
</tal:fields>
<tal:comment replace="nothing">Submit image</tal:comment>
<input type="image" id="submit2" name="submit2"
tal:attributes="src string: $appUrl/ui/ogone.gif; title python: _('custom_pay')"/>
</form>
</metal:view>
<tal:comment replace="nothing">Edit macro (none)</tal:comment>
<metal:edit define-macro="edit"></metal:edit>
<tal:comment replace="nothing">Cell macro (=view)</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/ogone/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro (none)</tal:comment>
<metal:search define-macro="search"></metal:search>

View file

@ -1,26 +0,0 @@
<tal:comment replace="nothing">View macro for a Pod.</tal:comment>
<metal:view define-macro="view">
<tal:askAction condition="widget/askAction"
define="doLabel python:'%s_askaction' % widget['labelId'];
chekboxId python: '%s_%s_cb' % (contextObj.UID(), name)">
<input type="checkbox" tal:attributes="name doLabel; id chekboxId"/>
<label tal:attributes="for chekboxId" class="discreet"
tal:content="python: _(doLabel)"></label>
</tal:askAction>
<img tal:repeat="podFormat python: tool.getPodInfo(contextObj, name)[1]"
tal:attributes="src string: $appUrl/ui/${podFormat}.png;
onClick python: 'generatePodDocument(\'%s\',\'%s\',\'%s\',\'%s\')' % (contextObj.UID(), name, podFormat, tool.getQueryInfo());
title podFormat/capitalize"
style="cursor:pointer"/>
</metal:view>
<tal:comment replace="nothing">Edit macro for a Pod.</tal:comment>
<metal:edit define-macro="edit"></metal:edit>
<tal:comment replace="nothing">Cell macro for a Pod.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/pod/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for a Pod.</tal:comment>
<metal:search define-macro="search"></metal:search>

View file

@ -1,285 +0,0 @@
<tal:comment replace="nothing">
We begin with some sub-macros used within macro "show" defined below.
</tal:comment>
<metal:objectTitle define-macro="objectTitle"
tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber);
navInfo python: test(appyType['isBack'], '', navInfo);
cssClass python: obj.getCssFor('title')">
<tal:comment replace="nothing">Displays the title of a referenced object, with a link on
it to reach the consult view for this object. If we are on a back reference, the link
allows to reach the correct page where the forward reference is defined. If we are
on a forward reference, the "nav" parameter is added to the URL for allowing to navigate
from one object to the next/previous on ui/view.</tal:comment>
<tal:sup replace="structure python: obj.getSupTitle(navInfo)"/>
<a tal:define="includeShownInfo includeShownInfo | python:False;
pageName python: appyType['isBack'] and appyType['backd']['pageName'] or 'main';
fullUrl python: obj.getUrl(page=pageName, nav=navInfo)"
tal:attributes="href fullUrl; class cssClass"
tal:content="python: (not includeShownInfo) and obj.Title() or contextObj.getReferenceLabel(fieldName, obj.appy())"></a><span
name="subTitle" tal:content="structure obj/getSubTitle"
tal:attributes="style python: showSubTitles and 'display:inline' or 'display:none'"></span>
</metal:objectTitle>
<metal:objectActions define-macro="objectActions">
<tal:comment replace="nothing">Displays icons for triggering actions on a given
referenced object (edit, delete, etc).</tal:comment>
<table class="noStyle" tal:define="isBack appyType/isBack">
<tr>
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
<td tal:condition="python: not isBack and (len(objs)&gt;1) and changeOrder and canWrite">
<tal:moveRef define="objectIndex python: contextObj.getAppyRefIndex(fieldName, obj);
ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'ChangeRefOrder\', {\'refObjectUid\':\'%s\', \'move\':\'**v**\'}' % (startNumber, obj.UID()))">
<img tal:condition="python: objectIndex &gt; 0" style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/arrowUp.png;
title python: _('move_up');
onClick python: ajaxBaseCall.replace('**v**', 'up')"/><img style="cursor:pointer"
tal:condition="python: objectIndex &lt; (totalNumber-1)"
tal:attributes="src string: $appUrl/ui/arrowDown.png;
title python: _('move_down');
onClick python: ajaxBaseCall.replace('**v**', 'down')"/>
</tal:moveRef>
</td>
<tal:comment replace="nothing">Workflow transitions</tal:comment>
<td tal:condition="python: obj.showTransitions('result')">
<tal:def define="targetObj python: obj">
<metal:transitions use-macro="app/ui/page/macros/transitions"/>
</tal:def>
</td>
<tal:comment replace="nothing">Edit</tal:comment>
<td tal:condition="python: not appyType['noForm'] and obj.mayEdit() and appyType['delete']">
<a tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber);"
tal:attributes="href python: obj.getUrl(mode='edit', page='main', nav=navInfo)">
<img tal:attributes="src string: $appUrl/ui/edit.png;
title python: _('object_edit')"/>
</a>
</td>
<tal:comment replace="nothing">Delete</tal:comment>
<td tal:condition="python: not isBack and appyType['delete'] and canWrite and obj.mayDelete()">
<img style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/delete.png;
onClick python:'onDeleteObject(\'%s\')' % obj.UID();
title python: _('object_delete')"/>
</td>
<tal:comment replace="nothing">Unlink</tal:comment>
<td tal:condition="python: not isBack and appyType['unlink'] and canWrite">
<img style="cursor:pointer"
tal:attributes="src string: $appUrl/ui/unlink.png;
onClick python:'onUnlinkObject(\'%s\',\'%s\',\'%s\')' % (contextObj.UID(), appyType['name'], obj.UID());
title python: _('object_unlink')"/>
</td>
</tr>
</table>
</metal:objectActions>
<tal:comment replace="nothing">Displays the "plus" icon that allows to add new object
through a reference widget. Indeed, If field was declared as "addable", we must provide
an icon for creating a new linked object (at least if multiplicities allow it).</tal:comment>
<metal:plus define-macro="plusIcon" tal:condition="showPlusIcon">
<input type="button" class="button"
tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], 0, totalNumber);
formCall python:'window.location=\'%s/do?action=Create&className=%s&nav=%s\'' % (folder.absolute_url(), linkedPortalType, navInfo);
formCall python: test(appyType['addConfirm'], 'askConfirm(\'script\', &quot;%s&quot;, &quot;%s&quot;)' % (formCall, addConfirmMsg), formCall);
noFormCall python: navBaseCall.replace('**v**', '%d, \'CreateWithoutForm\'' % startNumber);
noFormCall python: test(appyType['addConfirm'], 'askConfirm(\'script\', &quot;%s&quot;, &quot;%s&quot;)' % (noFormCall, addConfirmMsg), noFormCall)"
tal:attributes="style string: background-image: url($appUrl/ui/buttonAdd.png);
value python: _('add_ref');
onClick python: test(appyType['noForm'], noFormCall, formCall)"/>
</metal:plus>
<tal:comment replace="nothing">
This macro displays, in a cell header from a ref table, icons for sorting the
ref field according to the field that corresponds to this column.
</tal:comment>
<metal:sortIcons define-macro="sortIcons"
tal:define="ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'SortReference\', {\'sortKey\':\'%s\', \'reverse\':\'**v**\'}' % (startNumber, widget['name']))"
tal:condition="python: changeOrder and canWrite and tool.isSortable(widget['name'], objs[0].meta_type, 'ref')">
<img style="cursor:pointer"
tal:attributes="src string:$appUrl/ui/sortAsc.png;
onClick python: ajaxBaseCall.replace('**v**', 'False')"/>
<img style="cursor:pointer"
tal:attributes="src string:$appUrl/ui/sortDesc.png;
onClick python: ajaxBaseCall.replace('**v**', 'True')"/>
</metal:sortIcons>
<tal:comment replace="nothing">View macro for a Ref.</tal:comment>
<metal:view define-macro="view"
tal:define="dummy python: request.set('fieldName', widget['name'])">
<metal:ref use-macro="app/ui/widgets/ref/macros/viewContent"/>
</metal:view>
<tal:comment replace="nothing">
This macro is called by a XmlHttpRequest (or directly by the macro above)
for displaying the referred objects of a reference field.
</tal:comment>
<div metal:define-macro="viewContent"
tal:define="fieldName request/fieldName;
appyType python: contextObj.getAppyType(fieldName, asDict=True);
innerRef python: test(request.get('innerRef', False)=='True', True, False);
ajaxHookId python: contextObj.UID()+fieldName;
startNumber python: int(request.get('%s_startNumber' % ajaxHookId, 0));
tool contextObj/getTool;
_ python: tool.translate;
refObjects python:contextObj.getAppyRefs(fieldName, startNumber);
objs refObjects/objects;
totalNumber refObjects/totalNumber;
batchSize refObjects/batchSize;
folder contextObj/getCreateFolder;
linkedPortalType python: tool.getPortalType(appyType['klass']);
canWrite python: not appyType['isBack'] and contextObj.allows(appyType['writePermission']);
showPlusIcon python: contextObj.mayAddReference(fieldName);
atMostOneRef python: (appyType['multiplicity'][1] == 1) and (len(objs)&lt;=1);
addConfirmMsg python: appyType['addConfirm'] and _('%s_addConfirm' % appyType['labelId']) or '';
navBaseCall python: 'askRefField(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, contextObj.absolute_url(), fieldName, innerRef);
changeOrder python: contextObj.callField(fieldName, 'changeOrderEnabled', contextObj);
showSubTitles python: request.get('showSubTitles', 'true') == 'true'"
tal:attributes="id ajaxHookId">
<tal:comment replace="nothing">This macro displays the Reference widget on a "view" page.
The definition of "atMostOneRef" above may sound strange: we shouldn't check the actual number
of referenced objects. But for back references people often forget to specify multiplicities.
So concretely, multiplicities (0,None) are coded as (0,1).</tal:comment>
<tal:atMostOneReference condition="atMostOneRef">
<tal:comment replace="nothing">Display a simplified widget if maximum number of
referenced objects is 1.</tal:comment>
<table><tr valign="top">
<tal:comment replace="nothing">If there is no object...</tal:comment>
<tal:noObject condition="not:objs">
<td class="discreet" tal:content="python: _('no_ref')"></td>
<td><metal:plusIcon use-macro="app/ui/widgets/ref/macros/plusIcon"/></td>
</tal:noObject>
<tal:comment replace="nothing">If there is an object...</tal:comment>
<tal:objectIsPresent condition="python: objs">
<tal:obj repeat="obj objs">
<td tal:define="includeShownInfo python:True"><metal:showObjectTitle use-macro="app/ui/widgets/ref/macros/objectTitle" /></td>
</tal:obj>
</tal:objectIsPresent>
</tr></table>
</tal:atMostOneReference>
<tal:comment replace="nothing">Display a table in all other cases.</tal:comment>
<tal:anyNumberOfReferences condition="not: atMostOneRef">
<div tal:condition="python: not innerRef or showPlusIcon" style="margin-bottom: 4px">
(<span tal:replace="totalNumber"/>)
<metal:plus use-macro="app/ui/widgets/ref/macros/plusIcon"/>
<tal:comment replace="nothing">The search button if field is queryable</tal:comment>
<input type="button" class="button" tal:condition="python: objs and appyType['queryable']"
tal:attributes="style string: background-image: url($appUrl/ui/buttonSearch.png);
value python: _('search_title');
onclick python: 'window.location=\'%s/ui/search?className=%s&ref=%s:%s\'' % (tool.absolute_url(), linkedPortalType, contextObj.UID(), appyType['name'])">
</div>
<tal:comment replace="nothing">Appy (top) navigation</tal:comment>
<metal:nav use-macro="here/ui/navigate/macros/appyNavigate"/>
<tal:comment replace="nothing">No object is present</tal:comment>
<p class="discreet" tal:condition="not:objs" tal:content="python: _('no_ref')"></p>
<table width="100%" tal:condition="python: objs"
tal:attributes="class python:test(innerRef, 'innerAppyTable', '')">
<tr valign="bottom"><td>
<tal:comment replace="nothing">Show forward or backward reference(s)</tal:comment>
<table tal:attributes="class python:test(innerRef, '', 'list');
width python:test(innerRef, '100%', appyType['layouts']['view']['width']);">
<tal:infos define="columns python: objs[0].getColumnsSpecifiers(appyType['shownInfo'], dir)">
<tr tal:condition="appyType/showHeaders">
<th tal:repeat="column columns"
tal:attributes="width column/width; align column/align">
<tal:def define="widget column/field">
<span tal:content="python: _(widget['labelId'])"></span>
<metal:sortIcons use-macro="app/ui/widgets/ref/macros/sortIcons" />
<tal:sd define="className linkedPortalType">
<metal:details use-macro="context/ui/navigate/macros/showDetails"/>
</tal:sd>
</tal:def>
</th>
</tr>
<tal:row repeat="obj objs">
<tr valign="top" tal:define="odd repeat/obj/odd"
tal:attributes="class python:test(odd, 'even', 'odd')">
<td tal:repeat="column columns"
tal:attributes="width column/width; align column/align">
<tal:def define="widget column/field">
<tal:title condition="python: widget['name'] == 'title'">
<metal:title use-macro="app/ui/widgets/ref/macros/objectTitle"/>
<div tal:condition="obj/mayAct">
<metal:actions use-macro="app/ui/widgets/ref/macros/objectActions" />
</div>
</tal:title>
<tal:other condition="python: widget['name'] != 'title'">
<tal:field define="contextObj python:obj;
layoutType python: 'cell';
innerRef python:True"
condition="python: obj.showField(widget['name'], layoutType='result')">
<metal:field use-macro="app/ui/widgets/show/macros/field" />
</tal:field>
</tal:other>
</tal:def>
</td>
</tr>
</tal:row>
</tal:infos>
</table>
</td></tr>
</table>
<tal:comment replace="nothing">Appy (bottom) navigation</tal:comment>
<metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/>
</tal:anyNumberOfReferences>
</div>
<tal:comment replace="nothing">Edit macro for an Ref.</tal:comment>
<metal:editRef define-macro="edit"
tal:condition="widget/link"
tal:define="requestValue python: request.get(name, []);
inRequest python: request.has_key(name);
allObjects python: contextObj.getSelectableAppyRefs(name);
refUids python: [o.UID() for o in contextObj.getAppyRefs(name)['objects']];
isBeingCreated python: contextObj.isTemporary() or ('/portal_factory/' in contextObj.absolute_url())">
<select tal:attributes="name name;
size python: test(isMultiple, widget['height'], '');
multiple python: test(isMultiple, 'multiple', '')">
<option value="" tal:condition="not: isMultiple" tal:content="python: _('choose_a_value')"></option>
<tal:ref repeat="refObj allObjects">
<option tal:define="uid python: contextObj.getReferenceUid(refObj)"
tal:content="python: contextObj.getReferenceLabel(name, refObj)"
tal:attributes="value uid;
selected python:(inRequest and (uid in requestValue) or (not inRequest and ((uid in refUids)))) and True or False">
</option>
</tal:ref>
</select>
</metal:editRef>
<tal:comment replace="nothing">Cell macro for a Ref.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="app/ui/widgets/ref/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for a Ref.</tal:comment>
<metal:search define-macro="search">
<label tal:attributes="for widgetName" tal:content="python: _(widget['labelId'])"></label><br>&nbsp;&nbsp;
<tal:comment replace="nothing">The "and" / "or" radio buttons</tal:comment>
<tal:operator define="operName python: 'o_%s' % name;
orName python: '%s_or' % operName;
andName python: '%s_and' % operName;"
condition="python: widget['multiplicity'][1]!=1">
<input type="radio" tal:attributes="name operName; id orName" checked="checked" value="or"/>
<label tal:attributes="for orName" tal:content="python: _('search_or')"></label>
<input type="radio" tal:attributes="name operName; id andName" value="and"/>
<label tal:attributes="for andName" tal:content="python: _('search_and')"></label><br/>
</tal:operator>
<tal:comment replace="nothing">The list of values</tal:comment>
<select tal:attributes="name widgetName; size widget/sheight" multiple="multiple">
<tal:option repeat="v python: tool.getSearchValues(name, className)">
<option tal:define="uid python: v[0];
title python: tool.getReferenceLabel(name, v[1], className)"
tal:attributes="value uid; title title"
tal:content="python: tool.truncateValue(title, widget['swidth'])">
</option>
</tal:option>
</select>
</metal:search>

View file

@ -1,241 +0,0 @@
<tal:comment replace="nothing">
This macro shows the content of a layouted object, like a page or widget.
It requires:
contextObj The Zope object on which we are working
layoutType The kind of layout: "view"? "edit"? "cell"?
layout The layout object that will dictate how object content
will be rendered.
tagId The ID of the main tag for this layout.
Options:
contextMacro The base folder containing the macros to call for
rendering the elements within the layout.
Defaults to app.ui
tagName The name of the main tag for this layout (used
a.o. for master/slave relationships).
tagCss Some additional CSS class for the main tag
(ie, the CSS class for a slave).
Note: if layoutType is "cell", alignment and width are not taken into account:
we use the alignment of the column specification instead.
</tal:comment>
<metal:show define-macro="layout"
tal:define="contextMacro contextMacro| python: app.ui;
tagName tagName|python:'';
tagCss tagCss|python:'';
layoutCss layout/css_class;
isCell python: layoutType == 'cell'">
<table tal:attributes="cellpadding layout/cellpadding;
cellspacing layout/cellspacing;
width python: not isCell and layout['width'] or '';
align python: not isCell and tool.flipLanguageDirection(layout['align'], dir) or '';
class python: tagCss and ('%s %s' % (tagCss, layoutCss)).strip() or layoutCss;
style layout/style;
id tagId;
name tagName;">
<tal:comment replace="nothing">The table header row</tal:comment>
<tr tal:condition="layout/headerRow" tal:attributes="valign layout/headerRow/valign">
<th tal:repeat="cell layout/headerRow/cells"
tal:attributes="align python: tool.flipLanguageDirection(cell['align'], dir);
width cell/width;">
</th>
</tr>
<tal:comment replace="nothing">The table content</tal:comment>
<tr tal:repeat="row layout/rows" tal:attributes="valign row/valign">
<td tal:repeat="cell row/cells"
tal:attributes="align python: tool.flipLanguageDirection(cell['align'], dir);
colspan cell/colspan;
class python: test(repeat['cell'].end, '', 'cellGap')"><tal:content repeat="elem cell/content"><tal:field condition="python: elem == '?'"><metal:call use-macro="python: getattr(contextMacro, widget['type'].lower()).macros[layoutType]"/></tal:field><tal:other condition="python: elem != '?'"><metal:call use-macro="python: getattr(contextMacro, elem[0]).macros[elem[1]]"/></tal:other><img tal:condition="not: repeat/elem/end" tal:attributes="src string: $appUrl/ui/space.gif"/></tal:content>
</td>
</tr>
</table>
</metal:show>
<tal:comment replace="nothing">
This macro displays the widget corresponding to a given field. It requires:
contextObj The Zope object for which this widget must be rendered
page The page where the widget lies
layoutType "edit"? "view"? "cell?"
widget The widget to render
Optionally:
widgetName If the field to show is within a List, we cheat and
include, within the widgetName, the row index.
showChanges Do we need to show a variant of the field showing
successive changes made to it?
</tal:comment>
<metal:field define-macro="field"
tal:define="contextMacro python: app.ui.widgets;
showChanges showChanges| python:False;
layout python: widget['layouts'][layoutType];
name widgetName| widget/name;
sync python: widget['sync'][layoutType];
outerValue value|nothing;
rawValue python: contextObj.getFieldValue(name,onlyIfSync=True,layoutType=layoutType,outerValue=outerValue);
value python: contextObj.getFormattedFieldValue(name, rawValue, showChanges);
requestValue python: contextObj.getRequestFieldValue(name);
inRequest python: request.has_key(name);
errors errors | python: ();
inError python: name in errors;
isMultiple python: (widget['multiplicity'][1] == None) or (widget['multiplicity'][1] &gt; 1);
masterCss python: widget['slaves'] and ('master_%s' % name) or '';
slaveCss python: widget['master'] and ('slave_%s_%s' % (widget['masterName'], '_'.join(widget['masterValue']))) or '';
tagCss tagCss | python:'';
tagCss python: ('%s %s' % (slaveCss, tagCss)).strip();
tagId python: '%s_%s' % (contextObj.UID(), name);
tagName python: widget['master'] and 'slave' or '';">
<metal:layout use-macro="context/ui/widgets/show/macros/layout"/>
</metal:field>
<tal:comment replace="nothing">Call the previous macro, but from Ajax.</tal:comment>
<metal:afield define-macro="fieldAjax"
tal:define="widgetName request/fieldName;
layoutType python: request.get('layoutType', 'view');
showChanges python: request.get('showChanges', 'False') == 'True';
widget python: contextObj.getAppyType(widgetName, asDict=True);
page widget/pageName">
<metal:field use-macro="context/ui/widgets/show/macros/field"/>
</metal:afield>
<tal:comment replace="nothing">
This macro displays the widget corresponding to a group of widgets.
It requires:
contextObj The Zope object for which this widget must be rendered
page The page where the widget lies
layoutType "edit"? "view"? "cell?"
widget The widget to render
</tal:comment>
<metal:group define-macro="group"
tal:define="tagCss python: widget['master'] and ('slave_%s_%s' % (widget['masterName'], '_'.join(widget['masterValue']))) or '';
widgetCss widget/css_class;
groupCss python: tagCss and ('%s %s' % (tagCss, widgetCss)) or widgetCss;
tagName python: widget['master'] and 'slave' or '';
tagId python: '%s_%s' % (contextObj.UID(), widget['name'])">
<fieldset tal:condition="python: widget['style'] == 'fieldset'">
<legend tal:condition="widget/hasLabel">
<i tal:content="structure python: contextObj.translate(widget['labelId'])"></i>
<tal:help condition="widget/hasHelp">
<metal:call use-macro="app/ui/widgets/show/macros/help"/>
</tal:help>
</legend>
<div tal:condition="widget/hasDescr" class="discreet"
tal:content="structure python: contextObj.translate(widget['descrId'])"></div>
<metal:content use-macro="app/ui/widgets/show/macros/groupContent"/>
</fieldset>
<tal:asSection condition="python: widget['style'] not in ('fieldset', 'tabs')">
<metal:content use-macro="app/ui/widgets/show/macros/groupContent"/>
</tal:asSection>
<tal:asTabs condition="python: widget['style'] == 'tabs'">
<table tal:attributes="width widget/wide;
class groupCss;
id tagId; name tagName">
<tal:comment replace="nothing">First row: the tabs.</tal:comment>
<tr valign="middle"><td style="border-bottom: 1px solid #ff8040">
<table style="position:relative; bottom:-2px;" cellpadding="0" cellspacing="0">
<tr valign="bottom">
<tal:tab repeat="widgetRow widget/widgets">
<tal:id define="tabId python:'tab_%s_%d_%d' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']))">
<td><img tal:attributes="src string: $appUrl/ui/tabLeft.png;
id python: '%s_left' % tabId"/><td>
<td tal:attributes="style python:'background-image: url(%s/ui/tabBg.png)' % appUrl;
id tabId">
<a style="cursor:pointer"
tal:content="python: _('%s_col%d' % (widget['labelId'], repeat['widgetRow'].number()))"
tal:attributes="onClick python: 'showTab(\'%s_%d_%d\')' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']))"></a>
</td>
<td><img tal:attributes="src string: $appUrl/ui/tabRight.png;
id python: '%s_right' % tabId"/><td>
</tal:id>
</tal:tab>
</tr>
</table>
</td></tr>
<tal:comment replace="nothing">Other rows: the widgets.</tal:comment>
<tr tal:repeat="widgetRow widget/widgets"
tal:attributes="id python: 'tabcontent_%s_%d_%d' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']));
style python: test(repeat['widgetRow'].number()==1, 'display:table-row', 'display:none')">
<td tal:define="widget python: widgetRow[0]">
<tal:group condition="python: widget['type'] == 'group'">
<metal:call use-macro="app/ui/widgets/show/macros/group"/>
</tal:group>
<tal:field condition="python: widget['type'] != 'group'">
<metal:call use-macro="app/ui/widgets/show/macros/field"/>
</tal:field>
</td>
</tr>
</table>
<script type="text/javascript"
tal:content="python: 'initTab(\'tab_%s\', \'%s_1_%d\')' % (widget['name'], widget['name'], len(widget['widgets']))"></script>
</tal:asTabs>
</metal:group>
<tal:comment replace="nothing">
This macro displays the content of a group of widgets.
It is exclusively called by macro "group" above.
</tal:comment>
<table metal:define-macro="groupContent"
tal:define="cellgap widget/cellgap"
tal:attributes="width widget/wide;
align python: tool.flipLanguageDirection(widget['align'], dir);
class groupCss;
cellspacing widget/cellspacing;
cellpadding widget/cellpadding;
id tagId; name tagName">
<tal:comment replace="nothing">Display the title of the group if it is not rendered a fieldset.</tal:comment>
<tr tal:condition="python: (widget['style'] != 'fieldset') and widget['hasLabel']">
<td tal:attributes="colspan python: len(widget['columnsWidths']);
class widget/style;
align dleft">
<span tal:replace="structure python: contextObj.translate(widget['labelId'])"/>
<tal:help condition="widget/hasHelp">
<metal:call use-macro="app/ui/widgets/show/macros/help"/>
</tal:help>
</td>
</tr>
<tr tal:condition="python: (widget['style'] != 'fieldset') and widget['hasDescr']">
<td tal:attributes="colspan python: len(widget['columnsWidths'])" class="discreet"
tal:content="structure python: contextObj.translate(widget['descrId'])">
</td>
</tr>
<tr> <tal:comment replace="nothing">The column headers</tal:comment>
<th tal:repeat="colNb python:range(len(widget['columnsWidths']))"
tal:attributes="width python:widget['columnsWidths'][colNb];
align python: tool.flipLanguageDirection(widget['columnsAligns'][colNb], dir)"
tal:content="structure python: widget['hasHeaders'] and contextObj.translate('%s_col%d' % (widget['labelId'], colNb+1)) or ''">
</th>
</tr>
<tal:comment replace="nothing">The rows of widgets</tal:comment>
<tr tal:attributes="valign widget/valign" tal:repeat="widgetRow widget/widgets">
<td tal:repeat="widget widgetRow"
tal:attributes="colspan widget/colspan|python:1;
style python: test(repeat['widget'].number() != len(widgetRow), 'padding-right: %s'%cellgap, '')">
<tal:showWidget condition="widget">
<tal:group condition="python: widget['type'] == 'group'">
<metal:call use-macro="app/ui/widgets/show/macros/group"/>
</tal:group>
<tal:field condition="python: widget['type'] != 'group'">
<metal:call use-macro="app/ui/widgets/show/macros/field"/>
</tal:field>
</tal:showWidget>
</td>
</tr>
</table>
<tal:comment replace="nothing">Displays a field label.</tal:comment>
<tal:label metal:define-macro="label" condition="widget/hasLabel"><label tal:attributes="for widget/name" tal:condition="python: (widget['type'] != 'Action')" tal:content="structure python: contextObj.translate('label', field=widget)"></label></tal:label>
<tal:comment replace="nothing">Displays a field description.</tal:comment>
<tal:description metal:define-macro="description" condition="widget/hasDescr"><span class="discreet" tal:content="structure python: contextObj.translate('descr', field=widget)"></span>
</tal:description>
<tal:comment replace="nothing">Displays a field help.</tal:comment>
<tal:help metal:define-macro="help"><acronym tal:attributes="title python: contextObj.translate('help', field=widget)"><img tal:attributes="src string: $appUrl/ui/help.png"/></acronym></tal:help>
<tal:comment replace="nothing">Displays validation-error-related info about a field.</tal:comment>
<tal:validation metal:define-macro="validation"><acronym tal:condition="inError" tal:attributes="title python: errors[name]"><img tal:attributes="src string: $appUrl/ui/warning.png"/></acronym><img tal:condition="not: inError" tal:attributes="src string: $appUrl/ui/warning_no.gif"/></tal:validation>
<tal:comment replace="nothing">Displays the fact that a field is required.</tal:comment>
<tal:required metal:define-macro="required"><img tal:attributes="src string: $appUrl/ui/required.gif"/></tal:required>
<tal:comment replace="nothing">Button for showing changes to the field.</tal:comment>
<tal:changes metal:define-macro="changes" tal:condition="python: contextObj.hasHistory(name)"><img style="cursor:pointer" tal:condition="not: showChanges" tal:attributes="src string: $appUrl/ui/changes.png; onclick python: 'askField(\'%s\',\'%s\',\'view\',\'True\')' % (tagId, contextObj.absolute_url()); title python: _('changes_show')"/><img style="cursor:pointer" tal:condition="showChanges" tal:attributes="src string: $appUrl/ui/changesNo.png; onclick python: 'askField(\'%s\',\'%s\',\'view\',\'False\')' % (tagId, contextObj.absolute_url()); title python: _('changes_hide')"/></tal:changes>

View file

@ -1,132 +0,0 @@
<tal:comment replace="nothing">View macro for a String.</tal:comment>
<metal:view define-macro="view"
tal:define="fmt widget/format; isUrl widget/isUrl;
mayAjaxEdit python: not showChanges and widget['inlineEdit'] and contextObj.mayEdit(widget['writePermission'])">
<span tal:condition="python: fmt in (0, 3)">
<ul tal:condition="python: value and isMultiple">
<li tal:repeat="sv value"><i tal:content="structure sv"></i></li>
</ul>
<tal:singleValue condition="python: value and not isMultiple">
<tal:comment replace="nothing">A password</tal:comment>
<span tal:condition="python: fmt == 3">********</span>
<tal:comment replace="nothing">A URL</tal:comment>
<a tal:condition="python: (fmt != 3) and isUrl" target="_blank"
tal:attributes="href value" tal:content="value"></a>
<tal:comment replace="nothing">Any other value</tal:comment>
<span tal:condition="python: (fmt != 3) and not isUrl"
tal:replace="structure value"/>
</tal:singleValue>
</span>
<tal:comment replace="nothing">Text</tal:comment>
<span tal:condition="python: value and (fmt == 1)"
tal:replace="structure python: contextObj.formatText(value, format='html')"/>
<tal:comment replace="nothing">XHTML text</tal:comment>
<tal:xhtml condition="python: value and (fmt == 2)">
<div tal:condition="not: mayAjaxEdit" class="xhtml" tal:content="structure value"></div>
<div tal:condition="mayAjaxEdit" class="xhtml" contenteditable="true"
tal:attributes="id python: '%s_%s_ck' % (contextObj.UID(), name)"
tal:content="structure value">
</div>
<script tal:condition="mayAjaxEdit"
tal:content="python: contextObj.getEditorInlineInit(name)">
</script>
</tal:xhtml>
<input type="hidden" tal:condition="masterCss"
tal:attributes="class masterCss; value rawValue; name name; id name"/>
</metal:view>
<tal:comment replace="nothing">Edit macro for a String.</tal:comment>
<metal:edit define-macro="edit"
tal:define="fmt widget/format;
isSelect widget/isSelect;
isMaster widget/slaves;
isOneLine python: fmt in (0,3,4);
maxChars python: test(widget['maxChars'], widget['maxChars'], '')">
<tal:choice condition="isSelect">
<select tal:define="possibleValues python:contextObj.getPossibleValues(name, withTranslations=True, withBlankValue=True)"
tal:attributes="name name;
id name;
multiple python: isMultiple and 'multiple' or '';
onchange python: isMaster and 'updateSlaves(this)' or '';
class masterCss;
size python: isMultiple and widget['height'] or 1">
<option tal:repeat="possibleValue possibleValues"
tal:attributes="value python: possibleValue[0];
selected python:contextObj.fieldValueSelected(name, possibleValue[0], rawValue);
title python: possibleValue[1]"
tal:content="python:tool.truncateValue(possibleValue[1], widget['width'])"></option>
</select>
</tal:choice>
<tal:line condition="python: isOneLine and not isSelect">
<input tal:attributes="id name; name name; size widget/width; maxlength maxChars;
value python: test(inRequest, requestValue, value);
style python: 'text-transform:%s' % widget['transform'];
type python: (widget['format'] == 3) and 'password' or 'text'"/>
<tal:comment replace="nothing">Display a captcha if required</tal:comment>
<tal:captcha condition="python: widget['format'] == 4">
<span tal:define="challenge python: contextObj.getCaptchaChallenge(name)"
tal:content="python: _('captcha_text', mapping=challenge)">
</span>
</tal:captcha>
</tal:line>
<tal:textarea condition="python: fmt in (1,2)">
<textarea tal:attributes="id name; name name;
cols widget/width;
rows widget/height;
style python: 'text-transform:%s' % widget['transform'];
class python: (fmt==2) and ('rich_%s' % name) or ''"
tal:content="python: test(inRequest, requestValue, value)">
</textarea>
<script type="text/javascript" tal:condition="python: fmt == 2"
tal:content="python: contextObj.getEditorInit(name)">
</script>
</tal:textarea>
</metal:edit>
<tal:comment replace="nothing">Cell macro for a String.</tal:comment>
<metal:cell define-macro="cell"
tal:define="multipleValues python: value and isMultiple">
<tal:multiple condition="multipleValues"
content="python: ', '.join(value)">
</tal:multiple>
<tal:notMultiple condition="not: multipleValues">
<metal:call use-macro="app/ui/widgets/string/macros/view"/>
</tal:notMultiple>
</metal:cell>
<tal:comment replace="nothing">Search macro for a String.</tal:comment>
<metal:search define-macro="search">
<label tal:attributes="for widgetName" tal:content="python: _(widget['labelId'])"></label><br>&nbsp;&nbsp;
<tal:comment replace="nothing">Show a simple search field for most String fields.</tal:comment>
<tal:simpleSearch condition="not: widget/isSelect">
<input type="text" tal:define="maxChars python: test(widget['maxChars'], widget['maxChars'], '')"
tal:attributes="name python: '%s*string-%s' % (widgetName, widget['transform']);
maxlength maxChars; size widget/swidth;
style python: 'text-transform:%s' % widget['transform'];
value widget/sdefault"/>
</tal:simpleSearch>
<tal:comment replace="nothing">Show a multi-selection box for fields whose
validator defines a list of values, with a "AND/OR" checkbox.</tal:comment>
<tal:selectSearch condition="widget/isSelect">
<tal:comment replace="nothing">The "and" / "or" radio buttons</tal:comment>
<tal:operator define="operName python: 'o_%s' % name;
orName python: '%s_or' % operName;
andName python: '%s_and' % operName;"
condition="python: widget['multiplicity'][1]!=1">
<input type="radio" tal:attributes="name operName; id orName" checked="checked" value="or"/>
<label tal:attributes="for orName" tal:content="python: _('search_or')"></label>
<input type="radio" tal:attributes="name operName; id andName" value="and"/>
<label tal:attributes="for andName" tal:content="python: _('search_and')"></label><br/>
</tal:operator>
<tal:comment replace="nothing">The list of values</tal:comment>
<select tal:define="preSelected widget/sdefault"
tal:attributes="name widgetName; size widget/sheight" multiple="multiple">
<option tal:repeat="v python:tool.getPossibleValues(name, withTranslations=True, withBlankValue=False, className=className)"
tal:attributes="value python:v[0]; title python: v[1];
selected python: v[0] in preSelected"
tal:content="python: tool.truncateValue(v[1], widget['swidth'])">
</option>
</select>
</tal:selectSearch><br/>
</metal:search>

View file

@ -185,8 +185,8 @@ class ToolWrapper(AbstractWrapper):
<div class="portletContent"
var="searchInfo=ztool.getGroupedSearches(rootClass)">
<div class="portletTitle">
<a var="queryParam=searchInfo['default'] and \
searchInfo['default']['name'] or ''"
<a var="queryParam=searchInfo.default and \
searchInfo.default.name or ''"
href=":'%s?className=%s&amp;search=%s' % \
(queryUrl,rootClass,queryParam)"
class=":(not currentSearch and (currentClass==rootClass) and \
@ -246,9 +246,9 @@ class ToolWrapper(AbstractWrapper):
</x>
<!-- Predefined searches -->
<x for="widget in searchInfo['searches']">
<x if="widget['type']=='group'">:widget['px']</x>
<x if="widget['type']!='group'" var2="search=widget">:search['px']</x>
<x for="search in searchInfo.searches">
<x if="search.type == 'group'">:search.px</x>
<x if="search.type != 'group'">:search.pxView</x>
</x>
</div>
</x>
@ -285,29 +285,29 @@ class ToolWrapper(AbstractWrapper):
# will be the object whose page is shown; if the layouted object is a field,
# the layout target will be this field.
pxLayoutedObject = Px('''
<table var="layoutCss=layout['css_class'];
<table var="layoutCss=layout.css_class;
isCell=layoutType == 'cell'"
cellpadding=":layout['cellpadding']"
cellspacing=":layout['cellspacing']"
width=":not isCell and layout['width'] or ''"
cellpadding=":layout.cellpadding"
cellspacing=":layout.cellspacing"
width=":not isCell and layout.width or ''"
align=":not isCell and \
ztool.flipLanguageDirection(layout['align'], dir) or ''"
ztool.flipLanguageDirection(layout.align, dir) or ''"
class=":tagCss and ('%s %s' % (tagCss, layoutCss)).strip() or \
layoutCss"
style=":layout['style']" id=":tagId" name=":tagName">
style=":layout.style" id=":tagId" name=":tagName">
<!-- The table header row -->
<tr if="layout['headerRow']" valign=":layout['headerRow']['valign']">
<th for="cell in layout['headerRow']['cells']" width=":cell['width']"
align=":ztool.flipLanguageDirection(cell['align'], dir)">
<tr if="layout.headerRow" valign=":layout.headerRow.valign">
<th for="cell in layout.headerRow.cells" width=":cell.width"
align=":ztool.flipLanguageDirection(cell.align, dir)">
</th>
</tr>
<!-- The table content -->
<tr for="row in layout['rows']" valign=":row['valign']">
<td for="cell in row['cells']" colspan=":cell['colspan']"
align=":ztool.flipLanguageDirection(cell['align'], dir)"
<tr for="row in layout.rows" valign=":row.valign">
<td for="cell in row.cells" colspan=":cell.colspan"
align=":ztool.flipLanguageDirection(cell.align, dir)"
class=":not loop.cell.last and 'cellGap' or ''">
<x for="pxName in cell['content']">
<x for="pxName in cell.content">
<x var="px=(pxName == '?') and 'px%s' % layoutType.capitalize() \
or pxName">:getattr(layoutTarget, px)</x>
<img if="not loop.pxName.last" src=":url('space.gif')"/>
@ -423,9 +423,9 @@ class ToolWrapper(AbstractWrapper):
remember=True, sortBy=sortKey, sortOrder=sortOrder, \
filterKey=filterKey, filterValue=filterValue, \
refObject=refObject, refField=refField);
zobjects=queryResult['objects'];
totalNumber=queryResult['totalNumber'];
batchSize=queryResult['batchSize'];
zobjects=queryResult.objects;
totalNumber=queryResult.totalNumber;
batchSize=queryResult.batchSize;
batchNumber=len(zobjects);
ajaxHookId='queryResult';
navBaseCall='askQueryResult(%s,%s,%s,%s,**v**)' % \

View file

@ -69,9 +69,9 @@ class AbstractWrapper(object):
<x for="bc in breadcrumb" var2="nb=loop.bc.nb">
<img if="nb != 0" src=":url('to')"/>
<!-- Display only the title of the current object -->
<span if="nb == len(breadcrumb)-1">:bc['title']</span>
<span if="nb == len(breadcrumb)-1">:bc.title</span>
<!-- Display a link for parent objects -->
<a if="nb != len(breadcrumb)-1" href=":bc['url']">:bc['title']</a>
<a if="nb != len(breadcrumb)-1" href=":bc.url">:bc.title</a>
</x>
</td>
<!-- Object navigation -->
@ -292,9 +292,9 @@ class AbstractWrapper(object):
startNumber=int(startNumber);
batchSize=int(req.get('maxPerPage', 5));
historyInfo=zobj.getHistory(startNumber,batchSize=batchSize)"
if="historyInfo['events']"
var2="objs=historyInfo['events'];
totalNumber=historyInfo['totalNumber'];
if="historyInfo.events"
var2="objs=historyInfo.events;
totalNumber=historyInfo.totalNumber;
ajaxHookId='appyHistory';
navBaseCall='askObjectHistory(%s,%s,%d,**v**)' % \
(q(ajaxHookId), q(zobj.absolute_url()), batchSize)">
@ -516,7 +516,7 @@ class AbstractWrapper(object):
<!-- Refresh -->
<td if="zobj.isDebug()">
<a href="zobj.getUrl(mode=layoutType, page=page, refresh='yes')">
<a href=":zobj.getUrl(mode=layoutType, page=page, refresh='yes')">
<img title="Refresh" style="vertical-align:top" src=":url('refresh')"/>
</a>
</td>
@ -525,7 +525,7 @@ class AbstractWrapper(object):
# Displays the fields of a given page for a given object.
pxFields = Px('''
<table width=":layout['width']">
<table width=":layout.width">
<tr for="field in groupedFields">
<td if="field.type == 'group'">:field.pxView</td>
<td if="field.type != 'group'">:field.pxRender</td>
@ -911,7 +911,7 @@ class AbstractWrapper(object):
# returned by method executeResult.
res = tool.executeQuery(contentType, search=search,
maxResults=maxResults, noSecurity=noSecurity)
return [o.appy() for o in res['objects']]
return [o.appy() for o in res.objects]
def search1(self, *args, **kwargs):
'''Identical to m_search above, but returns a single result (if any).'''

View file

@ -300,8 +300,8 @@ def upper(s):
# ------------------------------------------------------------------------------
typeLetters = {'b': bool, 'i': int, 'j': long, 'f':float, 's':str, 'u':unicode,
'l': list, 'd': dict}
exts = {'py': ('.py', '.vpy', '.cpy'), 'pt': ('.pt', '.cpt')}
# ------------------------------------------------------------------------------
class CodeAnalysis:
'''This class holds information about some code analysis (line counts) that
spans some folder hierarchy.'''
@ -318,25 +318,6 @@ class CodeAnalysis:
'''Computes the total number of lines within analysed files.'''
return self.emptyLines + self.commentLines + self.codeLines
def analyseZptFile(self, theFile):
'''Analyses the ZPT file named p_fileName.'''
inDoc = False
for line in theFile:
stripped = line.strip()
# Manage a comment
if not inDoc and (line.find('<tal:comment ') != -1):
inDoc = True
if inDoc:
self.commentLines += 1
if line.find('</tal:comment>') != -1:
inDoc = False
continue
# Manage an empty line
if not stripped:
self.emptyLines += 1
else:
self.codeLines += 1
docSeps = ('"""', "'''")
def isPythonDoc(self, line, start, isStart=False):
'''Returns True if we find, in p_line, the start of a docstring (if
@ -389,8 +370,7 @@ class CodeAnalysis:
self.numberOfFiles += 1
theFile = file(fileName)
ext = os.path.splitext(fileName)[1]
if ext in exts['py']: self.analysePythonFile(theFile)
elif ext in exts['pt']: self.analyseZptFile(theFile)
if ext == '.py': self.analysePythonFile(theFile)
theFile.close()
def printReport(self):
@ -416,11 +396,9 @@ class LinesCounter:
else:
# It is a Python module
self.folder = os.path.dirname(folderOrModule.__file__)
# These dicts will hold information about analysed files
# These dict will hold information about analysed files.
self.python = {False: CodeAnalysis('Python'),
True: CodeAnalysis('Python (test)')}
self.zpt = {False: CodeAnalysis('ZPT'),
True: CodeAnalysis('ZPT (test)')}
# Are we currently analysing real or test code?
self.inTest = False
# Which paths to exclude from the analysis?
@ -430,7 +408,6 @@ class LinesCounter:
def printReport(self):
'''Displays on stdout a small analysis report about self.folder.'''
for zone in (False, True): self.python[zone].printReport()
for zone in (False, True): self.zpt[zone].printReport()
def isExcluded(self, path):
'''Must p_path be excluded from the analysis?'''
@ -456,10 +433,8 @@ class LinesCounter:
# Scan the files in this folder
for fileName in files:
ext = os.path.splitext(fileName)[1]
if ext in exts['py']:
if ext == '.py':
self.python[self.inTest].analyseFile(j(root, fileName))
elif ext in exts['pt']:
self.zpt[self.inTest].analyseFile(j(root, fileName))
self.printReport()
# ------------------------------------------------------------------------------