[gen] Goodbye Zope Page Templates.
This commit is contained in:
parent
1bd77d68c4
commit
04852360fa
|
@ -421,10 +421,6 @@ class Field:
|
||||||
self.hasLabel = self.hasLayoutElement('l', layouts)
|
self.hasLabel = self.hasLayoutElement('l', layouts)
|
||||||
self.hasDescr = self.hasLayoutElement('d', layouts)
|
self.hasDescr = self.hasLayoutElement('d', layouts)
|
||||||
self.hasHelp = self.hasLayoutElement('h', 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
|
return layouts
|
||||||
|
|
||||||
def hasLayoutElement(self, element, layouts):
|
def hasLayoutElement(self, element, layouts):
|
||||||
|
@ -444,7 +440,7 @@ class Field:
|
||||||
value for the Field constructor.'''
|
value for the Field constructor.'''
|
||||||
res = '{'
|
res = '{'
|
||||||
for k, v in self.layouts.iteritems():
|
for k, v in self.layouts.iteritems():
|
||||||
res += '"%s":"%s",' % (k, v['layoutString'])
|
res += '"%s":"%s",' % (k, v.layoutString)
|
||||||
res += '}'
|
res += '}'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,12 @@ from persistent.list import PersistentList
|
||||||
class Calendar(Field):
|
class Calendar(Field):
|
||||||
'''This field allows to produce an agenda (monthly view) and view/edit
|
'''This field allows to produce an agenda (monthly view) and view/edit
|
||||||
events on it.'''
|
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,
|
# Month view for a calendar. Called by pxView, and directly from the UI,
|
||||||
# via Ajax, when the user selects another month.
|
# via Ajax, when the user selects another month.
|
||||||
pxMonthView = Px('''
|
pxMonthView = Px('''
|
||||||
<div var="field=zobj.getAppyType(req['fieldName']);
|
<div var="ajaxHookId=zobj.UID() + field.name;
|
||||||
ajaxHookId=zobj.UID() + field.name;
|
|
||||||
month=req['month'];
|
month=req['month'];
|
||||||
monthDayOne=DateTime('%s/01' % month);
|
monthDayOne=DateTime('%s/01' % month);
|
||||||
today=DateTime('00:00');
|
today=DateTime('00:00');
|
||||||
|
@ -28,7 +27,7 @@ class Calendar(Field):
|
||||||
defaultDateMonth=defaultDate.strftime('%Y/%m');
|
defaultDateMonth=defaultDate.strftime('%Y/%m');
|
||||||
previousMonth=field.getSiblingMonth(month, 'previous');
|
previousMonth=field.getSiblingMonth(month, 'previous');
|
||||||
nextMonth=field.getSiblingMonth(month, 'next');
|
nextMonth=field.getSiblingMonth(month, 'next');
|
||||||
mayEdit=zobj.allows(widget['writePermission']);
|
mayEdit=zobj.allows(field.writePermission);
|
||||||
objUrl=zobj.absolute_url();
|
objUrl=zobj.absolute_url();
|
||||||
startDate=field.getStartDate(zobj);
|
startDate=field.getStartDate(zobj);
|
||||||
endDate=field.getEndDate(zobj);
|
endDate=field.getEndDate(zobj);
|
||||||
|
@ -106,10 +105,10 @@ class Calendar(Field):
|
||||||
<img class="clickable" style="visibility:hidden"
|
<img class="clickable" style="visibility:hidden"
|
||||||
var="info=field.getApplicableEventsTypesAt(zobj, date, \
|
var="info=field.getApplicableEventsTypesAt(zobj, date, \
|
||||||
allEventTypes, preComputed, True)"
|
allEventTypes, preComputed, True)"
|
||||||
if="info['eventTypes']" src=":url('plus')"
|
if="info.eventTypes" src=":url('plus')"
|
||||||
onclick=":'openEventPopup(%s, %s, %s, null, %s, %s)' % \
|
onclick=":'openEventPopup(%s, %s, %s, null, %s, %s)' % \
|
||||||
(q('new'), q(field.name), q(dayString), q(info['eventTypes']),\
|
(q('new'), q(field.name), q(dayString), q(info.eventTypes),\
|
||||||
q(info['message']))"/>
|
q(info.message))"/>
|
||||||
</x>
|
</x>
|
||||||
<!-- Icon for deleting an event -->
|
<!-- Icon for deleting an event -->
|
||||||
<img if="mayDelete" class="clickable" style="visibility:hidden"
|
<img if="mayDelete" class="clickable" style="visibility:hidden"
|
||||||
|
@ -117,15 +116,15 @@ class Calendar(Field):
|
||||||
onclick=":'openEventPopup(%s, %s, %s, %s, null, null)' % \
|
onclick=":'openEventPopup(%s, %s, %s, %s, null, null)' % \
|
||||||
(q('del'), q(field.name), q(dayString), q(spansDays))"/>
|
(q('del'), q(field.name), q(dayString), q(spansDays))"/>
|
||||||
<!-- A single event is allowed for the moment -->
|
<!-- 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>
|
<span style="color: grey">:field.getEventName(zobj, eventType)</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- Events from other calendars -->
|
<!-- Events from other calendars -->
|
||||||
<x if="otherCalendars"
|
<x if="otherCalendars"
|
||||||
var2="otherEvents=field.getOtherEventsAt(zobj, date, \
|
var2="otherEvents=field.getOtherEventsAt(zobj, date, \
|
||||||
otherCalendars)">
|
otherCalendars)">
|
||||||
<div style=":'color: %s; font-style: italic' % event['color']"
|
<div style=":'color: %s; font-style: italic' % event.color"
|
||||||
for="event in otherEvents">:event['name']</div>
|
for="event in otherEvents">:event.name</div>
|
||||||
</x>
|
</x>
|
||||||
<!-- Additional info -->
|
<!-- Additional info -->
|
||||||
<x var="info=field.getAdditionalInfoAt(zobj, date, preComputed)"
|
<x var="info=field.getAdditionalInfoAt(zobj, date, preComputed)"
|
||||||
|
@ -409,7 +408,7 @@ class Calendar(Field):
|
||||||
return res.__dict__
|
return res.__dict__
|
||||||
return res
|
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).'''
|
'''Returns the list of events that exist at some p_date (=day).'''
|
||||||
obj = obj.o # Ensure p_obj is not a wrapper.
|
obj = obj.o # Ensure p_obj is not a wrapper.
|
||||||
if not hasattr(obj.aq_base, self.name): return
|
if not hasattr(obj.aq_base, self.name): return
|
||||||
|
@ -422,16 +421,12 @@ class Calendar(Field):
|
||||||
days = months[month]
|
days = months[month]
|
||||||
day = date.day()
|
day = date.day()
|
||||||
if day not in days: return
|
if day not in days: return
|
||||||
if asDict:
|
return days[day]
|
||||||
res = [e.__dict__ for e in days[day]]
|
|
||||||
else:
|
|
||||||
res = days[day]
|
|
||||||
return res
|
|
||||||
|
|
||||||
def getEventTypeAt(self, obj, date):
|
def getEventTypeAt(self, obj, date):
|
||||||
'''Returns the event type of the first event defined at p_day, or None
|
'''Returns the event type of the first event defined at p_day, or None
|
||||||
if unspecified.'''
|
if unspecified.'''
|
||||||
events = self.getEventsAt(obj, date, asDict=False)
|
events = self.getEventsAt(obj, date)
|
||||||
if not events: return
|
if not events: return
|
||||||
return events[0].eventType
|
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
|
'''Returns True if, at p_date, an event is found of the same type as
|
||||||
p_otherEvents.'''
|
p_otherEvents.'''
|
||||||
if not otherEvents: return False
|
if not otherEvents: return False
|
||||||
events = self.getEventsAt(obj, date, asDict=False)
|
events = self.getEventsAt(obj, date)
|
||||||
if not events: return False
|
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):
|
def getOtherEventsAt(self, obj, date, otherCalendars):
|
||||||
'''Gets events that are defined in p_otherCalendars at some p_date.'''
|
'''Gets events that are defined in p_otherCalendars at some p_date.'''
|
||||||
res = []
|
res = []
|
||||||
for o, field, color in otherCalendars:
|
for o, field, color in otherCalendars:
|
||||||
events = field.getEventsAt(o.o, date, asDict=False)
|
events = field.getEventsAt(o.o, date)
|
||||||
if events:
|
if events:
|
||||||
eventType = events[0].eventType
|
eventType = events[0].eventType
|
||||||
eventName = field.getEventName(o.o, eventType)
|
eventName = field.getEventName(o.o, eventType)
|
||||||
info = Object(name=eventName, color=color)
|
info = Object(name=eventName, color=color)
|
||||||
res.append(info.__dict__)
|
res.append(info)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getEventName(self, obj, eventType):
|
def getEventName(self, obj, eventType):
|
||||||
|
|
|
@ -85,7 +85,6 @@ class List(Field):
|
||||||
# Tuples of (names, Field instances) determining the format of every
|
# Tuples of (names, Field instances) determining the format of every
|
||||||
# element in the list.
|
# element in the list.
|
||||||
self.fields = fields
|
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
|
# Force some layouting for sub-fields, if subLayouts are given. So the
|
||||||
# one who wants freedom on tuning layouts at the field level must
|
# one who wants freedom on tuning layouts at the field level must
|
||||||
# specify subLayouts=None.
|
# specify subLayouts=None.
|
||||||
|
|
|
@ -158,7 +158,7 @@ class Pod(Field):
|
||||||
objs = tool.o.executeQuery(obj.o.portal_type, searchName=search,
|
objs = tool.o.executeQuery(obj.o.portal_type, searchName=search,
|
||||||
sortBy=sortKey, sortOrder=sortOrder, filterKey=filterKey,
|
sortBy=sortKey, sortOrder=sortOrder, filterKey=filterKey,
|
||||||
filterValue=filterValue, maxResults='NO_LIMIT')
|
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.
|
# Add the field-specific context if present.
|
||||||
if specificContext:
|
if specificContext:
|
||||||
podContext.update(specificContext)
|
podContext.update(specificContext)
|
||||||
|
|
|
@ -198,7 +198,7 @@ class Ref(Field):
|
||||||
<td>
|
<td>
|
||||||
<!-- Show forward or backward reference(s) -->
|
<!-- Show forward or backward reference(s) -->
|
||||||
<table class=":not innerRef and 'list' or ''"
|
<table class=":not innerRef and 'list' or ''"
|
||||||
width=":innerRef and '100%' or field.layouts['view']['width']"
|
width=":innerRef and '100%' or field.layouts['view'].width"
|
||||||
var="columns=ztool.getColumnsSpecifiers(tiedClassName, \
|
var="columns=ztool.getColumnsSpecifiers(tiedClassName, \
|
||||||
field.shownInfo, dir)">
|
field.shownInfo, dir)">
|
||||||
<tr if="field.showHeaders">
|
<tr if="field.showHeaders">
|
||||||
|
@ -318,10 +318,8 @@ class Ref(Field):
|
||||||
self.isBack = False
|
self.isBack = False
|
||||||
# Initialise the backward reference
|
# Initialise the backward reference
|
||||||
self.back = back
|
self.back = back
|
||||||
self.backd = back.__dict__
|
|
||||||
back.isBack = True
|
back.isBack = True
|
||||||
back.back = self
|
back.back = self
|
||||||
back.backd = self.__dict__
|
|
||||||
# klass may be None in the case we are defining an auto-Ref to the
|
# 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,
|
# same class as the class where this field is defined. In this case,
|
||||||
# when defining the field within the class, write
|
# when defining the field within the class, write
|
||||||
|
@ -580,7 +578,7 @@ class Ref(Field):
|
||||||
def mayAdd(self, obj):
|
def mayAdd(self, obj):
|
||||||
'''May the user create a new referred object from p_obj via this Ref?'''
|
'''May the user create a new referred object from p_obj via this Ref?'''
|
||||||
# We can't (yet) do that on back references.
|
# 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
|
# Check if this Ref is addable
|
||||||
if callable(self.add):
|
if callable(self.add):
|
||||||
add = self.callMethod(obj, self.add)
|
add = self.callMethod(obj, self.add)
|
||||||
|
|
|
@ -147,9 +147,9 @@ class UiSearch:
|
||||||
pxView = Px('''
|
pxView = Px('''
|
||||||
<div class="portletSearch">
|
<div class="portletSearch">
|
||||||
<a href=":'%s?className=%s&search=%s' % \
|
<a href=":'%s?className=%s&search=%s' % \
|
||||||
(queryUrl, rootClass, search['name'])"
|
(queryUrl, rootClass, search.name)"
|
||||||
class=":search['name'] == currentSearch and 'portletCurrent' or ''"
|
class=":search.name == currentSearch and 'portletCurrent' or ''"
|
||||||
title=":search['translatedDescr']">:search['translated']</a>
|
title=":search.translatedDescr">:search.translated</a>
|
||||||
</div>''')
|
</div>''')
|
||||||
|
|
||||||
def __init__(self, search, className, tool):
|
def __init__(self, search, className, tool):
|
||||||
|
|
|
@ -19,7 +19,7 @@ homePage = '<tal:h define="dummy python: request.RESPONSE.redirect(' \
|
||||||
# Stuff for tracking user activity ---------------------------------------------
|
# Stuff for tracking user activity ---------------------------------------------
|
||||||
loggedUsers = {}
|
loggedUsers = {}
|
||||||
originalTraverse = None
|
originalTraverse = None
|
||||||
doNotTrack = ('.jpg','.gif','.png','.js','.class','.css')
|
doNotTrack = ('.jpg','.gif','.png','.js','.css')
|
||||||
|
|
||||||
def traverseWrapper(self, path, response=None, validated_hook=None):
|
def traverseWrapper(self, path, response=None, validated_hook=None):
|
||||||
'''This function is called every time a users gets a URL, this is used for
|
'''This function is called every time a users gets a URL, this is used for
|
||||||
|
@ -67,12 +67,9 @@ class ZopeInstaller:
|
||||||
|
|
||||||
def installUi(self):
|
def installUi(self):
|
||||||
'''Installs the user interface.'''
|
'''Installs the user interface.'''
|
||||||
# Some useful imports
|
# Some useful imports.
|
||||||
from OFS.Folder import manage_addFolder
|
from OFS.Folder import manage_addFolder
|
||||||
from OFS.Image import manage_addImage, manage_addFile
|
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.
|
# Delete the existing folder if it existed.
|
||||||
zopeContent = self.app.objectIds()
|
zopeContent = self.app.objectIds()
|
||||||
if 'ui' in zopeContent: self.app.manage_delObjects(['ui'])
|
if 'ui' in zopeContent: self.app.manage_delObjects(['ui'])
|
||||||
|
@ -99,33 +96,25 @@ class ZopeInstaller:
|
||||||
manage_addFolder(zopeFolder, name)
|
manage_addFolder(zopeFolder, name)
|
||||||
# Create files at this level
|
# Create files at this level
|
||||||
for name in files:
|
for name in files:
|
||||||
zopeName, ext = os.path.splitext(name)
|
ext = os.path.splitext(name)[1]
|
||||||
if ext not in ('.pt', '.py'):
|
if hasattr(zopeFolder.aq_base, name): continue
|
||||||
# In the ZODB, pages and scripts have their name without
|
|
||||||
# their extension.
|
|
||||||
zopeName = name
|
|
||||||
if hasattr(zopeFolder.aq_base, zopeName): continue
|
|
||||||
f = file(j(root, name))
|
f = file(j(root, name))
|
||||||
if zopeName == 'favicon.ico':
|
if name == 'favicon.ico':
|
||||||
if not hasattr(self.app, zopeName):
|
if not hasattr(self.app, name):
|
||||||
# Copy it at the root. Else, IE won't notice it.
|
# 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:
|
elif ext in gen.File.imageExts:
|
||||||
manage_addImage(zopeFolder, zopeName, f)
|
manage_addImage(zopeFolder, name, 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())
|
|
||||||
else:
|
else:
|
||||||
manage_addFile(zopeFolder, zopeName, f)
|
manage_addFile(zopeFolder, name, f)
|
||||||
f.close()
|
f.close()
|
||||||
# Update the home page
|
# Update the home page
|
||||||
if 'index_html' in zopeContent:
|
if 'index_html' in zopeContent:
|
||||||
self.app.manage_delObjects(['index_html'])
|
self.app.manage_delObjects(['index_html'])
|
||||||
|
from Products.PageTemplates.ZopePageTemplate import \
|
||||||
|
manage_addPageTemplate
|
||||||
manage_addPageTemplate(self.app, 'index_html', '', homePage)
|
manage_addPageTemplate(self.app, 'index_html', '', homePage)
|
||||||
# Update the error page
|
# Remove the error page.
|
||||||
if 'standard_error_message' in zopeContent:
|
if 'standard_error_message' in zopeContent:
|
||||||
self.app.manage_delObjects(['standard_error_message'])
|
self.app.manage_delObjects(['standard_error_message'])
|
||||||
|
|
||||||
|
|
|
@ -50,11 +50,7 @@ pxDict = {
|
||||||
'r': 'pxRequired', 'c': 'pxChanges'}
|
'r': 'pxRequired', 'c': 'pxChanges'}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class LayoutElement:
|
class Cell:
|
||||||
'''Abstract base class for any layout element.'''
|
|
||||||
def get(self): return self.__dict__
|
|
||||||
|
|
||||||
class Cell(LayoutElement):
|
|
||||||
'''Represents a cell in a row in a table.'''
|
'''Represents a cell in a row in a table.'''
|
||||||
def __init__(self, content, align, isHeader=False):
|
def __init__(self, content, align, isHeader=False):
|
||||||
self.align = align
|
self.align = align
|
||||||
|
@ -84,7 +80,7 @@ class Cell(LayoutElement):
|
||||||
self.colspan = int(digits)
|
self.colspan = int(digits)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Row(LayoutElement):
|
class Row:
|
||||||
'''Represents a row in a table.'''
|
'''Represents a row in a table.'''
|
||||||
def __init__(self, content, valign, isHeader=False):
|
def __init__(self, content, valign, isHeader=False):
|
||||||
self.valign = valign
|
self.valign = valign
|
||||||
|
@ -93,7 +89,7 @@ class Row(LayoutElement):
|
||||||
# Compute the row length
|
# Compute the row length
|
||||||
length = 0
|
length = 0
|
||||||
for cell in self.cells:
|
for cell in self.cells:
|
||||||
length += cell['colspan']
|
length += cell.colspan
|
||||||
self.length = length
|
self.length = length
|
||||||
|
|
||||||
def decodeCells(self, content, isHeader):
|
def decodeCells(self, content, isHeader):
|
||||||
|
@ -104,16 +100,16 @@ class Row(LayoutElement):
|
||||||
for char in content:
|
for char in content:
|
||||||
if char in cellDelimiters:
|
if char in cellDelimiters:
|
||||||
align = cellDelimiters[char]
|
align = cellDelimiters[char]
|
||||||
self.cells.append(Cell(cellContent, align, isHeader).get())
|
self.cells.append(Cell(cellContent, align, isHeader))
|
||||||
cellContent = ''
|
cellContent = ''
|
||||||
else:
|
else:
|
||||||
cellContent += char
|
cellContent += char
|
||||||
# Manage the last cell if any
|
# Manage the last cell if any
|
||||||
if cellContent:
|
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.'''
|
'''Represents a table where to dispose graphical elements.'''
|
||||||
simpleParams = ('style', 'css_class', 'cellpadding', 'cellspacing', 'width',
|
simpleParams = ('style', 'css_class', 'cellpadding', 'cellspacing', 'width',
|
||||||
'align')
|
'align')
|
||||||
|
@ -193,27 +189,26 @@ class Table(LayoutElement):
|
||||||
valign = rowDelimiters[char]
|
valign = rowDelimiters[char]
|
||||||
if self.isHeaderRow(rowContent):
|
if self.isHeaderRow(rowContent):
|
||||||
if not self.headerRow:
|
if not self.headerRow:
|
||||||
self.headerRow = Row(rowContent, valign,
|
self.headerRow = Row(rowContent, valign, isHeader=True)
|
||||||
isHeader=True).get()
|
|
||||||
else:
|
else:
|
||||||
self.rows.append(Row(rowContent, valign).get())
|
self.rows.append(Row(rowContent, valign))
|
||||||
rowContent = ''
|
rowContent = ''
|
||||||
else:
|
else:
|
||||||
rowContent += char
|
rowContent += char
|
||||||
# Manage the last row if any
|
# Manage the last row if any
|
||||||
if rowContent:
|
if rowContent:
|
||||||
self.rows.append(Row(rowContent, 'middle').get())
|
self.rows.append(Row(rowContent, 'middle'))
|
||||||
|
|
||||||
def removeElement(self, elem):
|
def removeElement(self, elem):
|
||||||
'''Removes given p_elem from myself.'''
|
'''Removes given p_elem from myself.'''
|
||||||
macroToRemove = pxDict[elem]
|
macroToRemove = pxDict[elem]
|
||||||
for row in self.rows:
|
for row in self.rows:
|
||||||
for cell in row['cells']:
|
for cell in row.cells:
|
||||||
if macroToRemove in cell['content']:
|
if macroToRemove in cell.content:
|
||||||
cell['content'].remove(macroToRemove)
|
cell.content.remove(macroToRemove)
|
||||||
|
|
||||||
# Some base layouts to use, for fields and pages -------------------------------
|
# Some base layouts to use, for fields and pages -------------------------------
|
||||||
# The default layouts for pages
|
# The default layouts for pages.
|
||||||
defaultPageLayouts = {
|
defaultPageLayouts = {
|
||||||
'view': Table('w|-b|', align="center"),
|
'view': Table('w|-b|', align="center"),
|
||||||
'edit': Table('w|-b|', width=None)}
|
'edit': Table('w|-b|', width=None)}
|
||||||
|
|
|
@ -61,12 +61,12 @@ class ToolMixin(BaseMixin):
|
||||||
try:
|
try:
|
||||||
url = tool.getHomePage()
|
url = tool.getHomePage()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# Bring Managers to the config, lead others to home.pt.
|
# Bring Managers to the config, lead others to pxHome.
|
||||||
user = self.getUser()
|
user = self.getUser()
|
||||||
if user.has_role('Manager'):
|
if user.has_role('Manager'):
|
||||||
url = self.goto(self.absolute_url())
|
url = self.goto(self.absolute_url())
|
||||||
else:
|
else:
|
||||||
url = self.goto('%s/home' % self.getApp().config.absolute_url())
|
url = self.goto('%s/home' % self.absolute_url())
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def getHomeObject(self):
|
def getHomeObject(self):
|
||||||
|
@ -96,12 +96,6 @@ class ToolMixin(BaseMixin):
|
||||||
'''Returns the absolute URL of this site.'''
|
'''Returns the absolute URL of this site.'''
|
||||||
return self.getApp().absolute_url()
|
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):
|
def getIncludeUrl(self, name, bg=False):
|
||||||
'''Gets the full URL of an external resource, like an image, a
|
'''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
|
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)
|
'inline;filename="%s"' % res.name)
|
||||||
return res.content
|
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):
|
def getAppName(self):
|
||||||
'''Returns the name of the application.'''
|
'''Returns the name of the application.'''
|
||||||
return self.getProductConfig().PROJECTNAME
|
return self.getProductConfig().PROJECTNAME
|
||||||
|
@ -270,7 +254,7 @@ class ToolMixin(BaseMixin):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getResultMode(self, className):
|
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?'''
|
as a grid?'''
|
||||||
klass = self.getAppyClass(className)
|
klass = self.getAppyClass(className)
|
||||||
if hasattr(klass, 'resultMode'): return klass.resultMode
|
if hasattr(klass, 'resultMode'): return klass.resultMode
|
||||||
|
@ -359,24 +343,20 @@ class ToolMixin(BaseMixin):
|
||||||
will be added to the query, or;
|
will be added to the query, or;
|
||||||
2) "customSearch": in this case, additional search criteria will
|
2) "customSearch": in this case, additional search criteria will
|
||||||
also be added to the query, but those criteria come from the
|
also be added to the query, but those criteria come from the
|
||||||
session (in key "searchCriteria") and were created from
|
session (in key "searchCriteria") and came from pxSearch.
|
||||||
search.pt.
|
|
||||||
|
|
||||||
We will retrieve objects from p_startNumber. If p_search is defined,
|
We will retrieve objects from p_startNumber. If p_search is defined,
|
||||||
it corresponds to a custom Search instance (instead of a predefined
|
it corresponds to a custom Search instance (instead of a predefined
|
||||||
named search like in p_searchName). If both p_searchName and p_search
|
named search like in p_searchName). If both p_searchName and p_search
|
||||||
are given, p_search is ignored.
|
are given, p_search is ignored.
|
||||||
|
|
||||||
This method returns a list of objects in the form of the
|
This method returns a list of objects in the form of an instance of
|
||||||
__dict__ attribute of an instance of SomeObjects (see in
|
SomeObjects (see in appy.gen.utils). If p_brainsOnly is True, it
|
||||||
appy.gen.utils). We return the __dict__ attribute instead of real
|
returns a list of brains instead (can be useful for some usages like
|
||||||
instance: that way, it can be used in ZPTs without security problems.
|
knowing the number of objects without needing to get information
|
||||||
If p_brainsOnly is True, it returns a list of brains instead (can be
|
about them). If no p_maxResults is specified, the method returns
|
||||||
useful for some usages like knowing the number of objects without
|
maximum self.numberOfResultsPerPage. The method returns all objects
|
||||||
needing to get information about them). If no p_maxResults is
|
if p_maxResults equals string "NO_LIMIT".
|
||||||
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
|
If p_noSecurity is True, it gets all the objects, even those that the
|
||||||
currently logged user can't see.
|
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
|
If p_refObject and p_refField are given, the query is limited to the
|
||||||
objects that are referenced from p_refObject through p_refField.'''
|
objects that are referenced from p_refObject through p_refField.'''
|
||||||
|
|
||||||
params = {'ClassName': className}
|
params = {'ClassName': className}
|
||||||
appyClass = self.getAppyClass(className, wrapper=True)
|
appyClass = self.getAppyClass(className, wrapper=True)
|
||||||
if not brainsOnly: params['batch'] = True
|
if not brainsOnly: params['batch'] = True
|
||||||
|
@ -447,7 +428,7 @@ class ToolMixin(BaseMixin):
|
||||||
i += 1
|
i += 1
|
||||||
uids[startNumber+i] = obj.UID()
|
uids[startNumber+i] = obj.UID()
|
||||||
self.REQUEST.SESSION['search_%s' % searchName] = uids
|
self.REQUEST.SESSION['search_%s' % searchName] = uids
|
||||||
return res.__dict__
|
return res
|
||||||
|
|
||||||
def getResultColumnsLayouts(self, className, refInfo):
|
def getResultColumnsLayouts(self, className, refInfo):
|
||||||
'''Returns the column layouts for displaying objects of
|
'''Returns the column layouts for displaying objects of
|
||||||
|
@ -711,7 +692,7 @@ class ToolMixin(BaseMixin):
|
||||||
|
|
||||||
def onSearchObjects(self):
|
def onSearchObjects(self):
|
||||||
'''This method is called when the user triggers a search from
|
'''This method is called when the user triggers a search from
|
||||||
search.pt.'''
|
pxSearch.'''
|
||||||
rq = self.REQUEST
|
rq = self.REQUEST
|
||||||
self.storeSearchCriteria()
|
self.storeSearchCriteria()
|
||||||
# Go to the screen that displays search results
|
# Go to the screen that displays search results
|
||||||
|
|
|
@ -273,7 +273,7 @@ class BaseMixin:
|
||||||
def removeMyLock(self, user, page):
|
def removeMyLock(self, user, page):
|
||||||
'''If p_user has set a lock on p_page, this method removes it. This
|
'''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
|
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.'''
|
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 \
|
if hasattr(self.aq_base, 'locks') and (page in self.locks) and \
|
||||||
(user.login == self.locks[page][0]):
|
(user.login == self.locks[page][0]):
|
||||||
|
@ -670,69 +670,6 @@ class BaseMixin:
|
||||||
if not allValues: return ''
|
if not allValues: return ''
|
||||||
return getattr(allValues[rowIndex], name, '')
|
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):
|
def mayAddReference(self, name):
|
||||||
'''May the user add references via Ref field named p_name in
|
'''May the user add references via Ref field named p_name in
|
||||||
p_folder?'''
|
p_folder?'''
|
||||||
|
@ -1134,7 +1071,7 @@ class BaseMixin:
|
||||||
else:
|
else:
|
||||||
event = history[i]
|
event = history[i]
|
||||||
res.append(event)
|
res.append(event)
|
||||||
return {'events': res, 'totalNumber': len(history)}
|
return Object(events=res, totalNumber=len(history))
|
||||||
|
|
||||||
def mayNavigate(self):
|
def mayNavigate(self):
|
||||||
'''May the currently logged user see the navigation panel linked to
|
'''May the currently logged user see the navigation panel linked to
|
||||||
|
@ -1258,64 +1195,6 @@ class BaseMixin:
|
||||||
self.reindex()
|
self.reindex()
|
||||||
return self.goto(self.getUrl(rq['HTTP_REFERER']))
|
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):
|
def appy(self):
|
||||||
'''Returns a wrapper object allowing to manipulate p_self the Appy
|
'''Returns a wrapper object allowing to manipulate p_self the Appy
|
||||||
way.'''
|
way.'''
|
||||||
|
@ -1480,20 +1359,6 @@ class BaseMixin:
|
||||||
for permission, creators in allCreators.iteritems():
|
for permission, creators in allCreators.iteritems():
|
||||||
updateRolesForPermission(permission, tuple(creators), folder)
|
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}
|
getUrlDefaults = {'page':True, 'nav':True}
|
||||||
def getUrl(self, base=None, mode='view', **kwargs):
|
def getUrl(self, base=None, mode='view', **kwargs):
|
||||||
'''Returns an URL for this object.
|
'''Returns an URL for this object.
|
||||||
|
@ -1568,8 +1433,8 @@ class BaseMixin:
|
||||||
klass = self.getClass()
|
klass = self.getClass()
|
||||||
if hasattr(klass, 'breadcrumb') and not klass.breadcrumb: return ()
|
if hasattr(klass, 'breadcrumb') and not klass.breadcrumb: return ()
|
||||||
# Compute the breadcrumb
|
# Compute the breadcrumb
|
||||||
res = [{'url': self.absolute_url(),
|
res = [Object(url=self.absolute_url(),
|
||||||
'title': self.getFieldValue('title', layoutType='view')}]
|
title=self.getFieldValue('title', layoutType='view'))]
|
||||||
parent = self.getParent()
|
parent = self.getParent()
|
||||||
if parent:
|
if parent:
|
||||||
res = parent.getBreadCrumb() + res
|
res = parent.getBreadCrumb() + res
|
||||||
|
@ -1681,14 +1546,7 @@ class BaseMixin:
|
||||||
layout = Table(layout)
|
layout = Table(layout)
|
||||||
else:
|
else:
|
||||||
layout = defaultPageLayouts[layoutType]
|
layout = defaultPageLayouts[layoutType]
|
||||||
return layout.get()
|
return layout
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def download(self, name=None):
|
def download(self, name=None):
|
||||||
'''Downloads the content of the file that is in the File field whose
|
'''Downloads the content of the file that is in the File field whose
|
||||||
|
@ -1753,44 +1611,6 @@ class BaseMixin:
|
||||||
raise Unauthorized
|
raise Unauthorized
|
||||||
return res
|
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):
|
def isTemporary(self):
|
||||||
'''Is this object temporary ?'''
|
'''Is this object temporary ?'''
|
||||||
parent = self.getParentNode()
|
parent = self.getParentNode()
|
||||||
|
@ -1802,11 +1622,4 @@ class BaseMixin:
|
||||||
'''This method is a general hook for transfering processing of a request
|
'''This method is a general hook for transfering processing of a request
|
||||||
to a given field, whose name must be in the request.'''
|
to a given field, whose name must be in the request.'''
|
||||||
return self.getAppyType(self.REQUEST['name']).process(self)
|
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
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Protos:
|
||||||
# List of attributes that can't be given to a Type constructor
|
# List of attributes that can't be given to a Type constructor
|
||||||
notInit = ('id', 'type', 'pythonType', 'slaves', 'isSelect', 'hasLabel',
|
notInit = ('id', 'type', 'pythonType', 'slaves', 'isSelect', 'hasLabel',
|
||||||
'hasDescr', 'hasHelp', 'required', 'filterable', 'validable',
|
'hasDescr', 'hasHelp', 'required', 'filterable', 'validable',
|
||||||
'backd', 'isBack', 'sync', 'pageName', 'masterName')
|
'isBack', 'sync', 'pageName', 'masterName')
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(self, appyType):
|
def get(self, appyType):
|
||||||
'''Returns a prototype instance for p_appyType.'''
|
'''Returns a prototype instance for p_appyType.'''
|
||||||
|
|
|
@ -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>
|
|
|
@ -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) {
|
function submitAppyForm(button) {
|
||||||
var theForm = document.getElementById('appyForm');
|
var theForm = document.getElementById('appyForm');
|
||||||
// On which button has the user clicked?
|
// On which button has the user clicked?
|
||||||
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -1,2 +0,0 @@
|
||||||
<metal:i define-macro="icons"></metal:i>
|
|
||||||
<metal:l define-macro="links"></metal:l>
|
|
109
gen/ui/import.pt
109
gen/ui/import.pt
|
@ -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>
|
|
|
@ -1,143 +0,0 @@
|
||||||
<div metal:define-macro="appyNavigate" tal:condition="python: totalNumber > 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">
|
|
||||||
<span tal:replace="python: startNumber+1"/>
|
|
||||||
<img tal:attributes="src string: $appUrl/ui/to.png"/>
|
|
||||||
<span tal:replace="python: startNumber+len(objs)"/> <b>//</b>
|
|
||||||
<span tal:replace="python: totalNumber"/>
|
|
||||||
</td>
|
|
||||||
<tal:comment replace="nothing">Go to the next page</tal:comment>
|
|
||||||
<td tal:define="sNumber python: startNumber + batchSize"
|
|
||||||
tal:condition="python: sNumber < 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">
|
|
||||||
<span tal:replace="python: currentNumber"/> <b>//</b>
|
|
||||||
<span tal:replace="python: totalNumber"/>
|
|
||||||
</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>
|
|
369
gen/ui/page.pt
369
gen/ui/page.pt
|
@ -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"/>
|
|
||||||
<span tal:replace="python: _('object_history')"></span> ||
|
|
||||||
</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">—
|
|
||||||
<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">
|
|
||||||
—
|
|
||||||
<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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
178
gen/ui/result.pt
178
gen/ui/result.pt
|
@ -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"/>
|
|
||||||
</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')">
|
|
||||||
— <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>
|
|
|
@ -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>
|
|
|
@ -1,212 +0,0 @@
|
||||||
<metal:main define-macro="main">
|
|
||||||
<tal:doctype tal:replace="structure string:<!DOCTYPE html PUBLIC
|
|
||||||
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">" />
|
|
||||||
<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"/>
|
|
||||||
<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>
|
|
|
@ -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>
|
|
|
@ -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\', "%s")' % (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>
|
|
|
@ -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>
|
|
||||||
<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>
|
|
|
@ -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) < grid[0][0].strftime(fmt));
|
|
||||||
goForward python: not endDate or (endDate.strftime(fmt) > 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 < startDate);
|
|
||||||
tooLate python: endDate and not tooEarly and (date > 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>
|
|
|
@ -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>
|
|
||||||
<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>
|
|
|
@ -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"> </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>
|
|
||||||
</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>
|
|
|
@ -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> -
|
|
||||||
<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>
|
|
|
@ -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>
|
|
||||||
<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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
||||||
<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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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)>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 > 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 < (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\', "%s", "%s")' % (formCall, addConfirmMsg), formCall);
|
|
||||||
noFormCall python: navBaseCall.replace('**v**', '%d, \'CreateWithoutForm\'' % startNumber);
|
|
||||||
noFormCall python: test(appyType['addConfirm'], 'askConfirm(\'script\', "%s", "%s")' % (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)<=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>
|
|
||||||
<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>
|
|
|
@ -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] > 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>
|
|
|
@ -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>
|
|
||||||
<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>
|
|
|
@ -185,8 +185,8 @@ class ToolWrapper(AbstractWrapper):
|
||||||
<div class="portletContent"
|
<div class="portletContent"
|
||||||
var="searchInfo=ztool.getGroupedSearches(rootClass)">
|
var="searchInfo=ztool.getGroupedSearches(rootClass)">
|
||||||
<div class="portletTitle">
|
<div class="portletTitle">
|
||||||
<a var="queryParam=searchInfo['default'] and \
|
<a var="queryParam=searchInfo.default and \
|
||||||
searchInfo['default']['name'] or ''"
|
searchInfo.default.name or ''"
|
||||||
href=":'%s?className=%s&search=%s' % \
|
href=":'%s?className=%s&search=%s' % \
|
||||||
(queryUrl,rootClass,queryParam)"
|
(queryUrl,rootClass,queryParam)"
|
||||||
class=":(not currentSearch and (currentClass==rootClass) and \
|
class=":(not currentSearch and (currentClass==rootClass) and \
|
||||||
|
@ -246,9 +246,9 @@ class ToolWrapper(AbstractWrapper):
|
||||||
</x>
|
</x>
|
||||||
|
|
||||||
<!-- Predefined searches -->
|
<!-- Predefined searches -->
|
||||||
<x for="widget in searchInfo['searches']">
|
<x for="search in searchInfo.searches">
|
||||||
<x if="widget['type']=='group'">:widget['px']</x>
|
<x if="search.type == 'group'">:search.px</x>
|
||||||
<x if="widget['type']!='group'" var2="search=widget">:search['px']</x>
|
<x if="search.type != 'group'">:search.pxView</x>
|
||||||
</x>
|
</x>
|
||||||
</div>
|
</div>
|
||||||
</x>
|
</x>
|
||||||
|
@ -285,29 +285,29 @@ class ToolWrapper(AbstractWrapper):
|
||||||
# will be the object whose page is shown; if the layouted object is a field,
|
# will be the object whose page is shown; if the layouted object is a field,
|
||||||
# the layout target will be this field.
|
# the layout target will be this field.
|
||||||
pxLayoutedObject = Px('''
|
pxLayoutedObject = Px('''
|
||||||
<table var="layoutCss=layout['css_class'];
|
<table var="layoutCss=layout.css_class;
|
||||||
isCell=layoutType == 'cell'"
|
isCell=layoutType == 'cell'"
|
||||||
cellpadding=":layout['cellpadding']"
|
cellpadding=":layout.cellpadding"
|
||||||
cellspacing=":layout['cellspacing']"
|
cellspacing=":layout.cellspacing"
|
||||||
width=":not isCell and layout['width'] or ''"
|
width=":not isCell and layout.width or ''"
|
||||||
align=":not isCell and \
|
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 \
|
class=":tagCss and ('%s %s' % (tagCss, layoutCss)).strip() or \
|
||||||
layoutCss"
|
layoutCss"
|
||||||
style=":layout['style']" id=":tagId" name=":tagName">
|
style=":layout.style" id=":tagId" name=":tagName">
|
||||||
|
|
||||||
<!-- The table header row -->
|
<!-- The table header row -->
|
||||||
<tr if="layout['headerRow']" valign=":layout['headerRow']['valign']">
|
<tr if="layout.headerRow" valign=":layout.headerRow.valign">
|
||||||
<th for="cell in layout['headerRow']['cells']" width=":cell['width']"
|
<th for="cell in layout.headerRow.cells" width=":cell.width"
|
||||||
align=":ztool.flipLanguageDirection(cell['align'], dir)">
|
align=":ztool.flipLanguageDirection(cell.align, dir)">
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- The table content -->
|
<!-- The table content -->
|
||||||
<tr for="row in layout['rows']" valign=":row['valign']">
|
<tr for="row in layout.rows" valign=":row.valign">
|
||||||
<td for="cell in row['cells']" colspan=":cell['colspan']"
|
<td for="cell in row.cells" colspan=":cell.colspan"
|
||||||
align=":ztool.flipLanguageDirection(cell['align'], dir)"
|
align=":ztool.flipLanguageDirection(cell.align, dir)"
|
||||||
class=":not loop.cell.last and 'cellGap' or ''">
|
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() \
|
<x var="px=(pxName == '?') and 'px%s' % layoutType.capitalize() \
|
||||||
or pxName">:getattr(layoutTarget, px)</x>
|
or pxName">:getattr(layoutTarget, px)</x>
|
||||||
<img if="not loop.pxName.last" src=":url('space.gif')"/>
|
<img if="not loop.pxName.last" src=":url('space.gif')"/>
|
||||||
|
@ -423,9 +423,9 @@ class ToolWrapper(AbstractWrapper):
|
||||||
remember=True, sortBy=sortKey, sortOrder=sortOrder, \
|
remember=True, sortBy=sortKey, sortOrder=sortOrder, \
|
||||||
filterKey=filterKey, filterValue=filterValue, \
|
filterKey=filterKey, filterValue=filterValue, \
|
||||||
refObject=refObject, refField=refField);
|
refObject=refObject, refField=refField);
|
||||||
zobjects=queryResult['objects'];
|
zobjects=queryResult.objects;
|
||||||
totalNumber=queryResult['totalNumber'];
|
totalNumber=queryResult.totalNumber;
|
||||||
batchSize=queryResult['batchSize'];
|
batchSize=queryResult.batchSize;
|
||||||
batchNumber=len(zobjects);
|
batchNumber=len(zobjects);
|
||||||
ajaxHookId='queryResult';
|
ajaxHookId='queryResult';
|
||||||
navBaseCall='askQueryResult(%s,%s,%s,%s,**v**)' % \
|
navBaseCall='askQueryResult(%s,%s,%s,%s,**v**)' % \
|
||||||
|
|
|
@ -69,9 +69,9 @@ class AbstractWrapper(object):
|
||||||
<x for="bc in breadcrumb" var2="nb=loop.bc.nb">
|
<x for="bc in breadcrumb" var2="nb=loop.bc.nb">
|
||||||
<img if="nb != 0" src=":url('to')"/>
|
<img if="nb != 0" src=":url('to')"/>
|
||||||
<!-- Display only the title of the current object -->
|
<!-- 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 -->
|
<!-- 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>
|
</x>
|
||||||
</td>
|
</td>
|
||||||
<!-- Object navigation -->
|
<!-- Object navigation -->
|
||||||
|
@ -292,9 +292,9 @@ class AbstractWrapper(object):
|
||||||
startNumber=int(startNumber);
|
startNumber=int(startNumber);
|
||||||
batchSize=int(req.get('maxPerPage', 5));
|
batchSize=int(req.get('maxPerPage', 5));
|
||||||
historyInfo=zobj.getHistory(startNumber,batchSize=batchSize)"
|
historyInfo=zobj.getHistory(startNumber,batchSize=batchSize)"
|
||||||
if="historyInfo['events']"
|
if="historyInfo.events"
|
||||||
var2="objs=historyInfo['events'];
|
var2="objs=historyInfo.events;
|
||||||
totalNumber=historyInfo['totalNumber'];
|
totalNumber=historyInfo.totalNumber;
|
||||||
ajaxHookId='appyHistory';
|
ajaxHookId='appyHistory';
|
||||||
navBaseCall='askObjectHistory(%s,%s,%d,**v**)' % \
|
navBaseCall='askObjectHistory(%s,%s,%d,**v**)' % \
|
||||||
(q(ajaxHookId), q(zobj.absolute_url()), batchSize)">
|
(q(ajaxHookId), q(zobj.absolute_url()), batchSize)">
|
||||||
|
@ -516,7 +516,7 @@ class AbstractWrapper(object):
|
||||||
|
|
||||||
<!-- Refresh -->
|
<!-- Refresh -->
|
||||||
<td if="zobj.isDebug()">
|
<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')"/>
|
<img title="Refresh" style="vertical-align:top" src=":url('refresh')"/>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -525,7 +525,7 @@ class AbstractWrapper(object):
|
||||||
|
|
||||||
# Displays the fields of a given page for a given object.
|
# Displays the fields of a given page for a given object.
|
||||||
pxFields = Px('''
|
pxFields = Px('''
|
||||||
<table width=":layout['width']">
|
<table width=":layout.width">
|
||||||
<tr for="field in groupedFields">
|
<tr for="field in groupedFields">
|
||||||
<td if="field.type == 'group'">:field.pxView</td>
|
<td if="field.type == 'group'">:field.pxView</td>
|
||||||
<td if="field.type != 'group'">:field.pxRender</td>
|
<td if="field.type != 'group'">:field.pxRender</td>
|
||||||
|
@ -911,7 +911,7 @@ class AbstractWrapper(object):
|
||||||
# returned by method executeResult.
|
# returned by method executeResult.
|
||||||
res = tool.executeQuery(contentType, search=search,
|
res = tool.executeQuery(contentType, search=search,
|
||||||
maxResults=maxResults, noSecurity=noSecurity)
|
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):
|
def search1(self, *args, **kwargs):
|
||||||
'''Identical to m_search above, but returns a single result (if any).'''
|
'''Identical to m_search above, but returns a single result (if any).'''
|
||||||
|
|
|
@ -300,8 +300,8 @@ def upper(s):
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
typeLetters = {'b': bool, 'i': int, 'j': long, 'f':float, 's':str, 'u':unicode,
|
typeLetters = {'b': bool, 'i': int, 'j': long, 'f':float, 's':str, 'u':unicode,
|
||||||
'l': list, 'd': dict}
|
'l': list, 'd': dict}
|
||||||
exts = {'py': ('.py', '.vpy', '.cpy'), 'pt': ('.pt', '.cpt')}
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
class CodeAnalysis:
|
class CodeAnalysis:
|
||||||
'''This class holds information about some code analysis (line counts) that
|
'''This class holds information about some code analysis (line counts) that
|
||||||
spans some folder hierarchy.'''
|
spans some folder hierarchy.'''
|
||||||
|
@ -318,25 +318,6 @@ class CodeAnalysis:
|
||||||
'''Computes the total number of lines within analysed files.'''
|
'''Computes the total number of lines within analysed files.'''
|
||||||
return self.emptyLines + self.commentLines + self.codeLines
|
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 = ('"""', "'''")
|
docSeps = ('"""', "'''")
|
||||||
def isPythonDoc(self, line, start, isStart=False):
|
def isPythonDoc(self, line, start, isStart=False):
|
||||||
'''Returns True if we find, in p_line, the start of a docstring (if
|
'''Returns True if we find, in p_line, the start of a docstring (if
|
||||||
|
@ -389,8 +370,7 @@ class CodeAnalysis:
|
||||||
self.numberOfFiles += 1
|
self.numberOfFiles += 1
|
||||||
theFile = file(fileName)
|
theFile = file(fileName)
|
||||||
ext = os.path.splitext(fileName)[1]
|
ext = os.path.splitext(fileName)[1]
|
||||||
if ext in exts['py']: self.analysePythonFile(theFile)
|
if ext == '.py': self.analysePythonFile(theFile)
|
||||||
elif ext in exts['pt']: self.analyseZptFile(theFile)
|
|
||||||
theFile.close()
|
theFile.close()
|
||||||
|
|
||||||
def printReport(self):
|
def printReport(self):
|
||||||
|
@ -416,11 +396,9 @@ class LinesCounter:
|
||||||
else:
|
else:
|
||||||
# It is a Python module
|
# It is a Python module
|
||||||
self.folder = os.path.dirname(folderOrModule.__file__)
|
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'),
|
self.python = {False: CodeAnalysis('Python'),
|
||||||
True: CodeAnalysis('Python (test)')}
|
True: CodeAnalysis('Python (test)')}
|
||||||
self.zpt = {False: CodeAnalysis('ZPT'),
|
|
||||||
True: CodeAnalysis('ZPT (test)')}
|
|
||||||
# Are we currently analysing real or test code?
|
# Are we currently analysing real or test code?
|
||||||
self.inTest = False
|
self.inTest = False
|
||||||
# Which paths to exclude from the analysis?
|
# Which paths to exclude from the analysis?
|
||||||
|
@ -430,7 +408,6 @@ class LinesCounter:
|
||||||
def printReport(self):
|
def printReport(self):
|
||||||
'''Displays on stdout a small analysis report about self.folder.'''
|
'''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.python[zone].printReport()
|
||||||
for zone in (False, True): self.zpt[zone].printReport()
|
|
||||||
|
|
||||||
def isExcluded(self, path):
|
def isExcluded(self, path):
|
||||||
'''Must p_path be excluded from the analysis?'''
|
'''Must p_path be excluded from the analysis?'''
|
||||||
|
@ -456,10 +433,8 @@ class LinesCounter:
|
||||||
# Scan the files in this folder
|
# Scan the files in this folder
|
||||||
for fileName in files:
|
for fileName in files:
|
||||||
ext = os.path.splitext(fileName)[1]
|
ext = os.path.splitext(fileName)[1]
|
||||||
if ext in exts['py']:
|
if ext == '.py':
|
||||||
self.python[self.inTest].analyseFile(j(root, fileName))
|
self.python[self.inTest].analyseFile(j(root, fileName))
|
||||||
elif ext in exts['pt']:
|
|
||||||
self.zpt[self.inTest].analyseFile(j(root, fileName))
|
|
||||||
self.printReport()
|
self.printReport()
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue