[gen] Class.popup: finalized the development of 'popup' classes.
This commit is contained in:
parent
ef68bb420b
commit
e11e754305
|
@ -307,7 +307,7 @@ class File(Field):
|
||||||
size=":field.width"/>
|
size=":field.width"/>
|
||||||
<script var="isDisabled=not value and 'false' or 'true'"
|
<script var="isDisabled=not value and 'false' or 'true'"
|
||||||
type="text/javascript">:'document.getElementById(%s).disabled=%s'%\
|
type="text/javascript">:'document.getElementById(%s).disabled=%s'%\
|
||||||
(q(fName), q(isDisabled))</script></x>''')
|
(fName, isDisabled)</script></x>''')
|
||||||
|
|
||||||
pxSearch = ''
|
pxSearch = ''
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,13 @@ class Phase:
|
||||||
class=":(aPage == page) and 'currentPage' or ''">
|
class=":(aPage == page) and 'currentPage' or ''">
|
||||||
<!-- First line: page name and icons -->
|
<!-- First line: page name and icons -->
|
||||||
<span if="not (singlePhase and singlePage)">
|
<span if="not (singlePhase and singlePage)">
|
||||||
<a href=":zobj.getUrl(page=aPage)">::aPageInfo.page.getLabel(zobj)</a>
|
<a href=":zobj.getUrl(page=aPage, \
|
||||||
|
inPopup=inPopup)">::aPageInfo.page.getLabel(zobj)</a>
|
||||||
<x var="locked=zobj.isLocked(user, aPage);
|
<x var="locked=zobj.isLocked(user, aPage);
|
||||||
editable=mayEdit and aPageInfo.showOnEdit and \
|
editable=mayEdit and aPageInfo.showOnEdit and \
|
||||||
aPageInfo.showEdit">
|
aPageInfo.showEdit">
|
||||||
<a if="editable and not locked"
|
<a if="editable and not locked"
|
||||||
href=":zobj.getUrl(mode='edit', page=aPage)">
|
href=":zobj.getUrl(mode='edit', page=aPage, inPopup=inPopup)">
|
||||||
<img src=":url('edit')" title=":_('object_edit')"/></a>
|
<img src=":url('edit')" title=":_('object_edit')"/></a>
|
||||||
<a if="editable and locked">
|
<a if="editable and locked">
|
||||||
<img style="cursor: help"
|
<img style="cursor: help"
|
||||||
|
|
159
fields/ref.py
159
fields/ref.py
|
@ -35,8 +35,7 @@ class Ref(Field):
|
||||||
# reach the consult view for this object. If we are on a back reference, the
|
# 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
|
# 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
|
# 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
|
# the URL for allowing to navigate from one object to the next/previous one.
|
||||||
# ui/view.
|
|
||||||
pxObjectTitle = Px('''
|
pxObjectTitle = Px('''
|
||||||
<x var="includeShownInfo=includeShownInfo|False;
|
<x var="includeShownInfo=includeShownInfo|False;
|
||||||
navInfo='ref.%s.%s:%s.%d.%d' % (zobj.id, field.name, \
|
navInfo='ref.%s.%s:%s.%d.%d' % (zobj.id, field.name, \
|
||||||
|
@ -45,12 +44,14 @@ class Ref(Field):
|
||||||
cssClass=tied.o.getCssFor('title')">
|
cssClass=tied.o.getCssFor('title')">
|
||||||
<x>::tied.o.getSupTitle(navInfo)</x>
|
<x>::tied.o.getSupTitle(navInfo)</x>
|
||||||
<a var="pageName=field.isBack and field.back.pageName or 'main';
|
<a var="pageName=field.isBack and field.back.pageName or 'main';
|
||||||
fullUrl=tied.o.getUrl(page=pageName, nav=navInfo)"
|
linkInPopup=inPopup or (target.target != '_self');
|
||||||
href=":fullUrl" class=":cssClass">:(not includeShownInfo) and \
|
fullUrl=tied.o.getUrl(page=pageName, nav=navInfo, \
|
||||||
|
inPopup=linkInPopup)"
|
||||||
|
href=":fullUrl" class=":cssClass" target=":target.target"
|
||||||
|
onclick=":target.openPopup">:(not includeShownInfo) and \
|
||||||
tied.title or field.getReferenceLabel(tied)
|
tied.title or field.getReferenceLabel(tied)
|
||||||
</a><span name="subTitle" style=":showSubTitles and 'display:inline' or \
|
</a><span name="subTitle" style=":showSubTitles and 'display:inline' or \
|
||||||
'display:none'">::tied.o.getSubTitle()</span>
|
'display:none'">::tied.o.getSubTitle()</span></x>''')
|
||||||
</x>''')
|
|
||||||
|
|
||||||
# This PX displays buttons for triggering global actions on several linked
|
# This PX displays buttons for triggering global actions on several linked
|
||||||
# objects (delete many, unlink many,...)
|
# objects (delete many, unlink many,...)
|
||||||
|
@ -84,7 +85,8 @@ class Ref(Field):
|
||||||
<table class="noStyle">
|
<table class="noStyle">
|
||||||
<tr>
|
<tr>
|
||||||
<!-- Arrows for moving objects up or down -->
|
<!-- Arrows for moving objects up or down -->
|
||||||
<td if="(totalNumber >1) and changeOrder and not inPickList"
|
<td if="(totalNumber >1) and changeOrder and not inPickList \
|
||||||
|
and not inMenu"
|
||||||
var2="ajaxBaseCall=navBaseCall.replace('**v**','%s,%s,{%s:%s,%s:%s}'%\
|
var2="ajaxBaseCall=navBaseCall.replace('**v**','%s,%s,{%s:%s,%s:%s}'%\
|
||||||
(q(startNumber), q('doChangeOrder'), q('refObjectUid'),
|
(q(startNumber), q('doChangeOrder'), q('refObjectUid'),
|
||||||
q(tiedUid), q('move'), q('**v**')))">
|
q(tiedUid), q('move'), q('**v**')))">
|
||||||
|
@ -108,8 +110,11 @@ class Ref(Field):
|
||||||
<!-- Edit -->
|
<!-- Edit -->
|
||||||
<td if="not field.noForm and tied.o.mayEdit()">
|
<td if="not field.noForm and tied.o.mayEdit()">
|
||||||
<a var="navInfo='ref.%s.%s:%s.%d.%d' % (zobj.id, field.name, \
|
<a var="navInfo='ref.%s.%s:%s.%d.%d' % (zobj.id, field.name, \
|
||||||
field.pageName, loop.tied.nb + 1 + startNumber, totalNumber)"
|
field.pageName, loop.tied.nb + 1 + startNumber, totalNumber);
|
||||||
href=":tied.o.getUrl(mode='edit', page='main', nav=navInfo)">
|
linkInPopup=inPopup or (target.target != '_self')"
|
||||||
|
href=":tied.o.getUrl(mode='edit', page='main', nav=navInfo, \
|
||||||
|
inPopup=linkInPopup)"
|
||||||
|
target=":target.target" onclick=":target.openPopup">
|
||||||
<img src=":url('edit')" title=":_('object_edit')"/></a>
|
<img src=":url('edit')" title=":_('object_edit')"/></a>
|
||||||
</td>
|
</td>
|
||||||
<!-- Delete -->
|
<!-- Delete -->
|
||||||
|
@ -140,24 +145,27 @@ class Ref(Field):
|
||||||
# Displays the button allowing to add a new object through a Ref field, if
|
# Displays the button allowing to add a new object through a Ref field, if
|
||||||
# it has been declared as addable and if multiplicities allow it.
|
# it has been declared as addable and if multiplicities allow it.
|
||||||
pxAdd = Px('''
|
pxAdd = Px('''
|
||||||
<input if="mayAdd and not inPickList" type="button"
|
<form if="mayAdd and not inPickList"
|
||||||
|
class=":inMenu and 'addFormMenu' or 'addForm'"
|
||||||
|
var2="formName='%s_%s_add' % (zobj.id, field.name)"
|
||||||
|
name=":formName" id=":formName" target=":target.target"
|
||||||
|
action=":'%s/do' % folder.absolute_url()">
|
||||||
|
<input type="hidden" name="action" value="Create"/>
|
||||||
|
<input type="hidden" name="className" value=":tiedClassName"/>
|
||||||
|
<input type="hidden" name="nav"
|
||||||
|
value=":'ref.%s.%s:%s.%d.%d' % (zobj.id, field.name, \
|
||||||
|
field.pageName, 0, totalNumber)"/>
|
||||||
|
<input type="hidden" name="popup"
|
||||||
|
value=":(inPopup or (target.target != '_self')) and '1' or '0'"/>
|
||||||
|
<input
|
||||||
|
type=":(field.addConfirm or field.noForm) and 'button' or 'submit'"
|
||||||
class="buttonSmall button"
|
class="buttonSmall button"
|
||||||
var2="navInfo='ref.%s.%s:%s.%d.%d' % (zobj.id, field.name, \
|
var="label=_('add_ref')" value=":label"
|
||||||
field.pageName, 0, totalNumber);
|
style=":'%s; %s' % (url('add', bg=True), \
|
||||||
formCall='goto(%s)' % \
|
ztool.getButtonWidth(label))"
|
||||||
q('%s/do?action=Create&className=%s&nav=%s' % \
|
onclick=":field.getOnAdd(q, formName, addConfirmMsg, target, \
|
||||||
(folder.absolute_url(), tiedClassName, navInfo));
|
navBaseCall, startNumber)"/>
|
||||||
formCall=not field.addConfirm and formCall or \
|
</form>''')
|
||||||
'askConfirm(%s,%s,%s)' % (q('script'), q(formCall), \
|
|
||||||
q(addConfirmMsg));
|
|
||||||
noFormCall=navBaseCall.replace('**v**', \
|
|
||||||
'%d,%s' % (startNumber, q('doCreateWithoutForm')));
|
|
||||||
noFormCall=not field.addConfirm and noFormCall or \
|
|
||||||
'askConfirm(%s, %s, %s)' % (q('script'), q(noFormCall), \
|
|
||||||
q(addConfirmMsg));
|
|
||||||
label=_('add_ref')"
|
|
||||||
style=":'%s; %s' % (url('add', bg=True), ztool.getButtonWidth(label))"
|
|
||||||
value=":label" onclick=":field.noForm and noFormCall or formCall"/>''')
|
|
||||||
|
|
||||||
# This PX displays, in a cell header from a ref table, icons for sorting the
|
# This PX displays, in a cell header from a ref table, icons for sorting the
|
||||||
# ref field according to the field that corresponds to this column.
|
# ref field according to the field that corresponds to this column.
|
||||||
|
@ -309,39 +317,60 @@ class Ref(Field):
|
||||||
req.get('showSubTitles', 'true') == 'true';
|
req.get('showSubTitles', 'true') == 'true';
|
||||||
subLabel='selectable_objects'">:field.pxViewList</x>''')
|
subLabel='selectable_objects'">:field.pxViewList</x>''')
|
||||||
|
|
||||||
# PX that displays referred objects as menus.
|
# PX that displays referred objects as dropdown menus.
|
||||||
pxViewMenus = Px('''
|
pxMenu = Px('''
|
||||||
<div if="objects"
|
|
||||||
for="menu in field.getLinkedObjectsByMenu(obj, objects)"
|
|
||||||
var2="dtc='display: table-cell'"
|
|
||||||
style=":not loop.menu.last and ('%s;padding-right:4px') % dtc or dtc">
|
|
||||||
|
|
||||||
<!-- A single object in the menu: show a clickable icon to get it -->
|
|
||||||
<a if="len(menu.objects) == 1" var2="tied=menu.objects[0]"
|
|
||||||
class="dropdownMenu" href=":field.getMenuUrl(zobj, tied)"
|
|
||||||
title=":tied.title">
|
|
||||||
<img if="menu.icon" src=":menu.icon"/><x
|
|
||||||
if="not menu.icon">:menu.text</x> 1</a>
|
|
||||||
|
|
||||||
<!-- Several objects: put them in a dropdown menu -->
|
|
||||||
<div if="len(menu.objects) > 1" class="dropdownMenu"
|
|
||||||
var2="dropdownId='%s_%s_%d' % (zobj.id, name, loop.menu.nb)"
|
|
||||||
onmouseover=":'toggleDropdown(%s)' % q(dropdownId)"
|
|
||||||
onmouseout=":'toggleDropdown(%s,%s)' % (q(dropdownId), q('none'))">
|
|
||||||
<img if="menu.icon" src=":menu.icon" title=":menu.text"/><x
|
<img if="menu.icon" src=":menu.icon" title=":menu.text"/><x
|
||||||
if="not menu.icon">:menu.text</x>
|
if="not menu.icon">:menu.text</x>
|
||||||
<!-- Display the number of objects in the menu (if more than one) -->
|
<!-- Nb of objects in the menu -->
|
||||||
<x if="len(menu.objects) > 1">:len(menu.objects)</x>
|
<x>:len(menu.objects)</x>''')
|
||||||
<!-- The dropdown menu containing annexes -->
|
|
||||||
|
pxViewMenus = Px('''
|
||||||
|
<x var2="dtc='display: table-cell'; inMenu=True">
|
||||||
|
<!-- No object is present -->
|
||||||
|
<div if="not objects" style=":'padding-left: 3px; %s' % dtc"
|
||||||
|
class="discreet">-</div>
|
||||||
|
|
||||||
|
<!-- One menu for every object type -->
|
||||||
|
<div for="menu in field.getLinkedObjectsByMenu(obj, objects)"
|
||||||
|
style=":not loop.menu.last and ('%s;padding-right:4px') % dtc or dtc">
|
||||||
|
<div class="dropdownMenu"
|
||||||
|
var2="dropdownId='%s_%s_%d' % (zobj.id, name, loop.menu.nb);
|
||||||
|
singleObject=len(menu.objects) == 1"
|
||||||
|
onmouseover=":'toggleDropdown(%s)' % q(dropdownId)"
|
||||||
|
onmouseout=":'toggleDropdown(%s,%s)' % (q(dropdownId), q('none'))">
|
||||||
|
|
||||||
|
<!-- The menu name and/or icon, that is clickable if there is a single
|
||||||
|
object in the menu. -->
|
||||||
|
<x if="singleObject" var2="tied=menu.objects[0]">
|
||||||
|
<a if="field.menuUrlMethod" class="dropdownMenu"
|
||||||
|
href=":field.getMenuUrl(zobj, tied)"
|
||||||
|
title=":tied.title">:field.pxMenu</a>
|
||||||
|
<a if="not field.menuUrlMethod" class="dropdownMenu"
|
||||||
|
var2="linkInPopup=inPopup or (target.target != '_self')"
|
||||||
|
target=":target.target" onclick=":target.openPopup"
|
||||||
|
href=":tied.o.getUrl(nav='',inPopup=linkInPopup)"
|
||||||
|
title=":tied.title">:field.pxMenu</a>
|
||||||
|
</x>
|
||||||
|
<x if="not singleObject">:field.pxMenu</x>
|
||||||
|
|
||||||
|
<!-- The dropdown menu containing tied objects -->
|
||||||
<div id=":dropdownId" class="dropdown" style="width:150px">
|
<div id=":dropdownId" class="dropdown" style="width:150px">
|
||||||
<div for="tied in menu.objects"
|
<div for="tied in menu.objects"
|
||||||
class=":not loop.tied.first and 'refMenuItem' or ''"
|
var2="startNumber=0;
|
||||||
var2="tiedUrl=field.getMenuUrl(zobj, tied)">
|
totalNumber=len(menu.objects);
|
||||||
<a href=":tiedUrl">:tied.title</a>
|
tiedUid=tied.uid"
|
||||||
|
class=":not loop.tied.first and 'refMenuItem' or ''">
|
||||||
|
<!-- A specific link may have to be computed from
|
||||||
|
field.menuUrlMethod -->
|
||||||
|
<a if="field.menuUrlMethod"
|
||||||
|
href=":field.getMenuUrl(zobj, tied)">:tied.title</a>
|
||||||
|
<!-- Show standard pxObjectTitle else -->
|
||||||
|
<x if="not field.menuUrlMethod">:field.pxObjectTitle</x>
|
||||||
|
<div if="tied.o.mayAct()">:field.pxObjectActions</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>''')
|
</div><x>:field.pxAdd</x></x> ''')
|
||||||
|
|
||||||
# Simplified widget showing minimal info about tied objects.
|
# Simplified widget showing minimal info about tied objects.
|
||||||
pxViewMinimal = Px('''
|
pxViewMinimal = Px('''
|
||||||
|
@ -359,6 +388,7 @@ class Ref(Field):
|
||||||
linkList=field.link == 'list';
|
linkList=field.link == 'list';
|
||||||
renderAll=req.get('scope') != 'objs';
|
renderAll=req.get('scope') != 'objs';
|
||||||
inPickList=False;
|
inPickList=False;
|
||||||
|
inMenu=False;
|
||||||
startNumber=field.getStartNumber(render, req, ajaxHookId);
|
startNumber=field.getStartNumber(render, req, ajaxHookId);
|
||||||
info=field.getValue(zobj,startNumber=startNumber,someObjects=True);
|
info=field.getValue(zobj,startNumber=startNumber,someObjects=True);
|
||||||
objects=info.objects;
|
objects=info.objects;
|
||||||
|
@ -368,6 +398,7 @@ class Ref(Field):
|
||||||
batchNumber=len(objects);
|
batchNumber=len(objects);
|
||||||
folder=zobj.getCreateFolder();
|
folder=zobj.getCreateFolder();
|
||||||
tiedClassName=ztool.getPortalType(field.klass);
|
tiedClassName=ztool.getPortalType(field.klass);
|
||||||
|
target=ztool.getLinksTargetInfo(field.klass);
|
||||||
mayEdit=not field.isBack and zobj.mayEdit(field.writePermission);
|
mayEdit=not field.isBack and zobj.mayEdit(field.writePermission);
|
||||||
mayUnlink=mayEdit and field.getAttribute(zobj, 'unlink');
|
mayUnlink=mayEdit and field.getAttribute(zobj, 'unlink');
|
||||||
mayAdd=mayEdit and field.mayAdd(zobj, checkMayEdit=False);
|
mayAdd=mayEdit and field.mayAdd(zobj, checkMayEdit=False);
|
||||||
|
@ -729,6 +760,7 @@ class Ref(Field):
|
||||||
def getLinkedObjectsByMenu(self, obj, objects):
|
def getLinkedObjectsByMenu(self, obj, objects):
|
||||||
'''This method groups p_objects into sub-lists of objects, grouped by
|
'''This method groups p_objects into sub-lists of objects, grouped by
|
||||||
menu (happens when self.render == 'menus').'''
|
menu (happens when self.render == 'menus').'''
|
||||||
|
if not objects: return ()
|
||||||
res = []
|
res = []
|
||||||
# We store in "menuIds" the already encountered menus:
|
# We store in "menuIds" the already encountered menus:
|
||||||
# ~{s_menuId : i_indexInRes}~
|
# ~{s_menuId : i_indexInRes}~
|
||||||
|
@ -948,6 +980,29 @@ class Ref(Field):
|
||||||
obj.raiseUnauthorized("User can't write Ref field '%s' (%s)." % \
|
obj.raiseUnauthorized("User can't write Ref field '%s' (%s)." % \
|
||||||
(self.name, may.msg))
|
(self.name, may.msg))
|
||||||
|
|
||||||
|
def getOnAdd(self, q, formName, addConfirmMsg, target, navBaseCall,
|
||||||
|
startNumber):
|
||||||
|
'''Computes the JS code to execute when button "add" is clicked.'''
|
||||||
|
if self.noForm:
|
||||||
|
# Ajax-refresh the Ref with a special param to link a newly created
|
||||||
|
# object.
|
||||||
|
res = navBaseCall.replace('**v**',
|
||||||
|
"%d,'doCreateWithoutForm'" % startNumber)
|
||||||
|
if self.addConfirm:
|
||||||
|
res = "askConfirm('script', %s, %s)" % \
|
||||||
|
(q(res, False), q(addConfirmMsg))
|
||||||
|
else:
|
||||||
|
# In the basic case, no JS code is executed: target.openPopup is
|
||||||
|
# empty and the button-related form is submitted in the main page.
|
||||||
|
res = target.openPopup
|
||||||
|
if self.addConfirm and not target.openPopup:
|
||||||
|
res = "askConfirm('form','%s',%s)" % (formName,q(addConfirmMsg))
|
||||||
|
elif self.addConfirm and target.openPopup:
|
||||||
|
res = "askConfirm('form+script',%s,%s)" % \
|
||||||
|
(q(formName + '+' + target.openPopup, False), \
|
||||||
|
q(addConfirmMsg))
|
||||||
|
return res
|
||||||
|
|
||||||
def getCbJsInit(self, obj):
|
def getCbJsInit(self, obj):
|
||||||
'''When checkboxes are enabled, this method defines a JS associative
|
'''When checkboxes are enabled, this method defines a JS associative
|
||||||
array (named "_appy_objs_cbs") that will store checkboxes' statuses.
|
array (named "_appy_objs_cbs") that will store checkboxes' statuses.
|
||||||
|
|
|
@ -416,10 +416,11 @@ class ToolMixin(BaseMixin):
|
||||||
sub-lists of p_sub elements.'''
|
sub-lists of p_sub elements.'''
|
||||||
return sutils.splitList(l, sub)
|
return sutils.splitList(l, sub)
|
||||||
|
|
||||||
def quote(self, s):
|
def quote(self, s, escapeWithEntity=True):
|
||||||
'''Returns the quoted version of p_s.'''
|
'''Returns the quoted version of p_s.'''
|
||||||
if not isinstance(s, basestring): s = str(s)
|
if not isinstance(s, basestring): s = str(s)
|
||||||
s = s.replace('\r\n', '').replace('\n', '').replace("'", "'")
|
repl = escapeWithEntity and ''' or "\\'"
|
||||||
|
s = s.replace('\r\n', '').replace('\n', '').replace("'", repl)
|
||||||
return "'%s'" % s
|
return "'%s'" % s
|
||||||
|
|
||||||
def getLayoutType(self):
|
def getLayoutType(self):
|
||||||
|
@ -789,7 +790,7 @@ class ToolMixin(BaseMixin):
|
||||||
startNumber += batchSize
|
startNumber += batchSize
|
||||||
return startNumber
|
return startNumber
|
||||||
|
|
||||||
def getNavigationInfo(self):
|
def getNavigationInfo(self, inPopup=False):
|
||||||
'''Extracts navigation information from request/nav and returns an
|
'''Extracts navigation information from request/nav and returns an
|
||||||
object with the info that a page can use for displaying object
|
object with the info that a page can use for displaying object
|
||||||
navigation.'''
|
navigation.'''
|
||||||
|
@ -841,7 +842,7 @@ class ToolMixin(BaseMixin):
|
||||||
uids = getattr(masterObj, fieldName)
|
uids = getattr(masterObj, fieldName)
|
||||||
# Display the reference widget at the page where the current object
|
# Display the reference widget at the page where the current object
|
||||||
# lies.
|
# lies.
|
||||||
startNumberKey = '%s%s_startNumber' % (masterObj.UID(), fieldName)
|
startNumberKey = '%s%s_startNumber' % (masterObj.id, fieldName)
|
||||||
startNumber = self.computeStartNumberFrom(res.currentNumber-1,
|
startNumber = self.computeStartNumberFrom(res.currentNumber-1,
|
||||||
res.totalNumber, batchSize)
|
res.totalNumber, batchSize)
|
||||||
res.sourceUrl = masterObj.getUrl(**{startNumberKey:startNumber,
|
res.sourceUrl = masterObj.getUrl(**{startNumberKey:startNumber,
|
||||||
|
@ -895,7 +896,7 @@ class ToolMixin(BaseMixin):
|
||||||
sibling = brain.getObject()
|
sibling = brain.getObject()
|
||||||
setattr(res, urlKey, sibling.getUrl(\
|
setattr(res, urlKey, sibling.getUrl(\
|
||||||
nav=newNav % (index + 1),
|
nav=newNav % (index + 1),
|
||||||
page=rq.get('page', 'main')))
|
page=rq.get('page', 'main'), inPopup=inPopup))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getGroupedSearchFields(self, searchInfo):
|
def getGroupedSearchFields(self, searchInfo):
|
||||||
|
@ -1368,4 +1369,30 @@ class ToolMixin(BaseMixin):
|
||||||
# Set a minimum width for small labels.
|
# Set a minimum width for small labels.
|
||||||
if len(label) < 15: return 'width:130px'
|
if len(label) < 15: return 'width:130px'
|
||||||
return 'padding-left: 26px; padding-right: 8px'
|
return 'padding-left: 26px; padding-right: 8px'
|
||||||
|
|
||||||
|
def getLinksTargetInfo(self, klass):
|
||||||
|
'''Appy allows to open links to view or edit instances of p_klass
|
||||||
|
either via the same browser window, or via a popup. This method
|
||||||
|
returns info about that, as an object having 2 attributes:
|
||||||
|
- target is "_self" if the link leads to the same browser window,
|
||||||
|
"appyIFrame" if the link must be opened in a popup;
|
||||||
|
- openPopup is unused if target is "_self" and contains the
|
||||||
|
Javascript code to open the popup.'''
|
||||||
|
res = Object(target='_self', openPopup='')
|
||||||
|
if hasattr(klass, 'popup'):
|
||||||
|
res.target = 'appyIFrame'
|
||||||
|
d = klass.popup
|
||||||
|
if isinstance(d, basestring):
|
||||||
|
# Width only
|
||||||
|
params = int(d[:-2])
|
||||||
|
else:
|
||||||
|
# Width and height
|
||||||
|
params = "%s, %s" % (d[0][:-2], d[1][:-2])
|
||||||
|
res.openPopup = "openPopup('iframePopup',null,%s)" % params
|
||||||
|
return res
|
||||||
|
|
||||||
|
def backFromPopup(self):
|
||||||
|
'''Returns the PX allowing to close the iframe popup and refresh the
|
||||||
|
base page.'''
|
||||||
|
return self.appy().pxBack({'ztool': self})
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -196,7 +196,8 @@ class BaseMixin:
|
||||||
className = rq.get('className')
|
className = rq.get('className')
|
||||||
# Create the params to add to the URL we will redirect the user to
|
# Create the params to add to the URL we will redirect the user to
|
||||||
# create the object.
|
# create the object.
|
||||||
urlParams = {'mode':'edit', 'page':'main', 'nav':''}
|
urlParams = {'mode':'edit', 'page':'main', 'nav':'',
|
||||||
|
'inPopup':rq.get('popup') == '1'}
|
||||||
initiator, initiatorPage, initiatorField = self.getInitiatorInfo()
|
initiator, initiatorPage, initiatorField = self.getInitiatorInfo()
|
||||||
if initiator:
|
if initiator:
|
||||||
# The object to create will be linked to an initiator object through
|
# The object to create will be linked to an initiator object through
|
||||||
|
@ -379,12 +380,15 @@ class BaseMixin:
|
||||||
tool = self.getTool()
|
tool = self.getTool()
|
||||||
errorMessage = self.translate('validation_error')
|
errorMessage = self.translate('validation_error')
|
||||||
isNew = self.isTemporary()
|
isNew = self.isTemporary()
|
||||||
|
inPopup = rq.get('popup') == '1'
|
||||||
# If this object is created from an initiator, get info about him.
|
# If this object is created from an initiator, get info about him.
|
||||||
initiator, initiatorPage, initiatorField = self.getInitiatorInfo()
|
initiator, initiatorPage, initiatorField = self.getInitiatorInfo()
|
||||||
# If the user clicked on 'Cancel', go back to the previous page.
|
# If the user clicked on 'Cancel', go back to the previous page.
|
||||||
buttonClicked = rq.get('button')
|
buttonClicked = rq.get('button')
|
||||||
if buttonClicked == 'cancel':
|
if buttonClicked == 'cancel':
|
||||||
if initiator:
|
if inPopup:
|
||||||
|
back = tool.backFromPopup()
|
||||||
|
elif initiator:
|
||||||
# Go back to the initiator page.
|
# Go back to the initiator page.
|
||||||
urlBack = initiator.getUrl(page=initiatorPage, nav='')
|
urlBack = initiator.getUrl(page=initiatorPage, nav='')
|
||||||
else:
|
else:
|
||||||
|
@ -395,6 +399,7 @@ class BaseMixin:
|
||||||
urlBack = self.getUrl()
|
urlBack = self.getUrl()
|
||||||
self.say(self.translate('object_canceled'))
|
self.say(self.translate('object_canceled'))
|
||||||
self.removeLock(rq['page'])
|
self.removeLock(rq['page'])
|
||||||
|
if inPopup: return back
|
||||||
return self.goto(urlBack)
|
return self.goto(urlBack)
|
||||||
|
|
||||||
# Object for storing validation errors
|
# Object for storing validation errors
|
||||||
|
@ -433,17 +438,17 @@ class BaseMixin:
|
||||||
if not msg: msg = self.translate('object_saved')
|
if not msg: msg = self.translate('object_saved')
|
||||||
# If the object has already been deleted (ie, it is a kind of transient
|
# If the object has already been deleted (ie, it is a kind of transient
|
||||||
# object like a one-shot form and has already been deleted in method
|
# object like a one-shot form and has already been deleted in method
|
||||||
# onEdit), redirect to the main site page.
|
# onEdit) or if the user can't access the object anymore, redirect him
|
||||||
if not getattr(obj.getParentNode().aq_base, obj.id, None):
|
# to the user's home page.
|
||||||
return self.goto(tool.getSiteUrl(), msg)
|
if not getattr(obj.getParentNode().aq_base, obj.id, None) or \
|
||||||
# If the user can't access the object anymore, redirect him to its home
|
not obj.mayView():
|
||||||
# page.
|
if inPopup: return tool.backFromPopup()
|
||||||
if not obj.mayView(): return self.goto(tool.getHomePage(), msg)
|
return self.goto(tool.getHomePage(), msg)
|
||||||
if (buttonClicked == 'save') or saveConfirmed:
|
if (buttonClicked == 'save') or saveConfirmed:
|
||||||
obj.say(msg)
|
obj.say(msg)
|
||||||
|
if inPopup: return tool.backFromPopup()
|
||||||
if isNew and initiator:
|
if isNew and initiator:
|
||||||
return self.goto(initiator.getUrl(page=initiatorPage, nav=''))
|
return self.goto(initiator.getUrl(page=initiatorPage, nav=''))
|
||||||
else:
|
|
||||||
return self.goto(obj.getUrl())
|
return self.goto(obj.getUrl())
|
||||||
if buttonClicked == 'previous':
|
if buttonClicked == 'previous':
|
||||||
# Go to the previous page for this object.
|
# Go to the previous page for this object.
|
||||||
|
@ -462,29 +467,30 @@ class BaseMixin:
|
||||||
# I do not use gotoEdit here because I really need to
|
# I do not use gotoEdit here because I really need to
|
||||||
# redirect the user to the edit page. Indeed, the object
|
# redirect the user to the edit page. Indeed, the object
|
||||||
# edit URL may have moved from temp_folder to another place.
|
# edit URL may have moved from temp_folder to another place.
|
||||||
return self.goto(obj.getUrl(mode='edit', page=pageName))
|
return self.goto(obj.getUrl(mode='edit', page=pageName,
|
||||||
|
inPopup=inPopup))
|
||||||
else:
|
else:
|
||||||
return self.goto(obj.getUrl(page=pageName))
|
return self.goto(obj.getUrl(page=pageName, inPopup=inPopup))
|
||||||
else:
|
else:
|
||||||
obj.say(msg)
|
obj.say(msg)
|
||||||
return self.goto(obj.getUrl())
|
return self.goto(obj.getUrl(inPopup=inPopup))
|
||||||
if buttonClicked == 'next':
|
if buttonClicked == 'next':
|
||||||
# Go to the next page for this object.
|
# Go to the next page for this object.
|
||||||
# We remember page name, because the next method may set a new
|
# We remember page name, because the next method may set a new
|
||||||
# current page if the current one is not visible anymore.
|
# current page if the current one is not visible anymore.
|
||||||
pageName = rq['page']
|
|
||||||
phaseObj = self.getAppyPhases(currentOnly=True, layoutType='edit')
|
phaseObj = self.getAppyPhases(currentOnly=True, layoutType='edit')
|
||||||
pageName, pageInfo = phaseObj.getNextPage(pageName)
|
pageName, pageInfo = phaseObj.getNextPage(rq['page'])
|
||||||
if pageName:
|
if pageName:
|
||||||
# Return to the edit or view page?
|
# Return to the edit or view page?
|
||||||
if pageInfo.showOnEdit:
|
if pageInfo.showOnEdit:
|
||||||
# Same remark as above (click on "previous").
|
# Same remark as above (click on "previous").
|
||||||
return self.goto(obj.getUrl(mode='edit', page=pageName))
|
return self.goto(obj.getUrl(mode='edit', page=pageName,
|
||||||
|
inPopup=inPopup))
|
||||||
else:
|
else:
|
||||||
return self.goto(obj.getUrl(page=pageName))
|
return self.goto(obj.getUrl(page=pageName, inPopup=inPopup))
|
||||||
else:
|
else:
|
||||||
obj.say(msg)
|
obj.say(msg)
|
||||||
return self.goto(obj.getUrl())
|
return self.goto(obj.getUrl(inPopup=inPopup))
|
||||||
return obj.gotoEdit()
|
return obj.gotoEdit()
|
||||||
|
|
||||||
def reindex(self, indexes=None, unindex=False):
|
def reindex(self, indexes=None, unindex=False):
|
||||||
|
@ -1326,11 +1332,15 @@ class BaseMixin:
|
||||||
return layoutType in showValue
|
return layoutType in showValue
|
||||||
|
|
||||||
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', inPopup=False, **kwargs):
|
||||||
'''Returns an URL for this object.
|
'''Returns an URL for this object.
|
||||||
* If p_base is None, it will be the base URL for this object
|
* If p_base is None, it will be the base URL for this object
|
||||||
(ie, Zope self.absolute_url()).
|
(ie, Zope self.absolute_url()).
|
||||||
* p_mode can be "edit", "view" or "raw" (a non-param, base URL)
|
* p_mode can be "edit", "view" or "raw" (a non-param, base URL)
|
||||||
|
* If p_inPopup is True, the link will be opened in the Appy iframe.
|
||||||
|
An additional param "popup=1" will be added to URL params, in order
|
||||||
|
to tell Appy that the link target will be shown in a popup, in a
|
||||||
|
minimalistic way (no portlet...).
|
||||||
* p_kwargs can store additional parameters to add to the URL.
|
* p_kwargs can store additional parameters to add to the URL.
|
||||||
In this dict, every value that is a string will be added to the
|
In this dict, every value that is a string will be added to the
|
||||||
URL as-is. Every value that is True will be replaced by the value
|
URL as-is. Every value that is True will be replaced by the value
|
||||||
|
@ -1355,6 +1365,7 @@ class BaseMixin:
|
||||||
if not kwargs: kwargs = self.getUrlDefaults
|
if not kwargs: kwargs = self.getUrlDefaults
|
||||||
if 'page' not in kwargs: kwargs['page'] = True
|
if 'page' not in kwargs: kwargs['page'] = True
|
||||||
if 'nav' not in kwargs: kwargs['nav'] = True
|
if 'nav' not in kwargs: kwargs['nav'] = True
|
||||||
|
kwargs['popup'] = inPopup and '1' or '0'
|
||||||
# Create URL parameters from kwargs
|
# Create URL parameters from kwargs
|
||||||
params = []
|
params = []
|
||||||
for name, value in kwargs.iteritems():
|
for name, value in kwargs.iteritems():
|
||||||
|
@ -1392,18 +1403,19 @@ class BaseMixin:
|
||||||
return False
|
return False
|
||||||
if parent.meta_type not in ('Folder', 'Temporary Folder'): return parent
|
if parent.meta_type not in ('Folder', 'Temporary Folder'): return parent
|
||||||
|
|
||||||
def getBreadCrumb(self):
|
def getBreadCrumb(self, inPopup=False):
|
||||||
'''Gets breadcrumb info about this object and its parents (if it must
|
'''Gets breadcrumb info about this object and its parents (if it must
|
||||||
be shown).'''
|
be shown).'''
|
||||||
# Return an empty breadcrumb if it must not be shown.
|
# Return an empty breadcrumb if it must not be shown.
|
||||||
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 = [Object(url=self.absolute_url(),
|
res = [Object(url=self.getUrl(inPopup=inPopup),
|
||||||
title=self.getFieldValue('title', layoutType='view'))]
|
title=self.getFieldValue('title', layoutType='view'))]
|
||||||
|
# In a popup: limit the breadcrumb to the current object.
|
||||||
|
if inPopup: return res
|
||||||
parent = self.getParent()
|
parent = self.getParent()
|
||||||
if parent:
|
if parent: res = parent.getBreadCrumb() + res
|
||||||
res = parent.getBreadCrumb() + res
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def index_html(self):
|
def index_html(self):
|
||||||
|
|
|
@ -714,3 +714,7 @@ msgstr ""
|
||||||
#. Default: "You are not allowed to consult this."
|
#. Default: "You are not allowed to consult this."
|
||||||
msgid "unauthorized"
|
msgid "unauthorized"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "Close"
|
||||||
|
msgid "window_close"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -74,6 +74,7 @@ input.buttonSmall { width: 100px !important; font-size: 85%; height: 18px;
|
||||||
width: 600px; border: 1px #F0C36D solid; padding: 6px;
|
width: 600px; border: 1px #F0C36D solid; padding: 6px;
|
||||||
background-color: #F9EDBE; text-align: center; margin-left: -300px;
|
background-color: #F9EDBE; text-align: center; margin-left: -300px;
|
||||||
border-radius: 2px 2px 2px 2px; box-shadow: 0 2px 4px #A9A9A9 }
|
border-radius: 2px 2px 2px 2px; box-shadow: 0 2px 4px #A9A9A9 }
|
||||||
|
.messagePopup { width: 80%; top: 0; left: 0; margin-left: 10px }
|
||||||
.focus { font-size: 90%; margin: 7px 0 7px 0; padding: 7px;
|
.focus { font-size: 90%; margin: 7px 0 7px 0; padding: 7px;
|
||||||
background-color: #d7dee4; border-radius: 2px 2px 2px 2px;
|
background-color: #d7dee4; border-radius: 2px 2px 2px 2px;
|
||||||
box-shadow: 0 2px 4px #A9A9A9 }
|
box-shadow: 0 2px 4px #A9A9A9 }
|
||||||
|
@ -101,6 +102,8 @@ td.search { padding-top: 8px }
|
||||||
font-weight: normal; text-align: left; z-index: 2 }
|
font-weight: normal; text-align: left; z-index: 2 }
|
||||||
.dropdownMenu { cursor: pointer; font-size: 93%; position: relative }
|
.dropdownMenu { cursor: pointer; font-size: 93%; position: relative }
|
||||||
.dropdown a:hover { text-decoration: underline }
|
.dropdown a:hover { text-decoration: underline }
|
||||||
|
.addForm { display: inline }
|
||||||
|
.addFormMenu { display: table-cell; padding-left: 7px }
|
||||||
.list { margin-bottom: 3px }
|
.list { margin-bottom: 3px }
|
||||||
.list td, .list th { border: 3px solid #ededed; color: grey;
|
.list td, .list th { border: 3px solid #ededed; color: grey;
|
||||||
padding: 3px 5px 3px 5px }
|
padding: 3px 5px 3px 5px }
|
||||||
|
@ -127,8 +130,8 @@ td.search { padding-top: 8px }
|
||||||
.odd { background-color: #f6f6f6 }
|
.odd { background-color: #f6f6f6 }
|
||||||
.odd2 { background-color: #f2f2f2 }
|
.odd2 { background-color: #f2f2f2 }
|
||||||
.refMenuItem { border-top: grey 1px dashed; margin: 3px 0; padding-top: 3px }
|
.refMenuItem { border-top: grey 1px dashed; margin: 3px 0; padding-top: 3px }
|
||||||
.summary { margin-bottom: 5px; background-color: #f9f9f9;
|
.summary { margin-bottom: 5px; background-color: whitesmoke;
|
||||||
border: 2px solid #f9f9f9 }
|
border: 3px solid white }
|
||||||
.by { padding: 5px; color: grey; font-size: 97% }
|
.by { padding: 5px; color: grey; font-size: 97% }
|
||||||
.underline { border-bottom: 1px dotted grey }
|
.underline { border-bottom: 1px dotted grey }
|
||||||
.state { font-weight: bold; border-bottom: 1px dashed grey }
|
.state { font-weight: bold; border-bottom: 1px dashed grey }
|
||||||
|
|
|
@ -703,7 +703,7 @@ function protectAppyForm() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions for opening and closing a popup
|
// Functions for opening and closing a popup
|
||||||
function openPopup(popupId, msg) {
|
function openPopup(popupId, msg, width, height) {
|
||||||
// Put the message into the popup
|
// Put the message into the popup
|
||||||
if (msg) {
|
if (msg) {
|
||||||
var msgHook = (popupId == 'alertPopup')? 'appyAlertText': 'appyConfirmText';
|
var msgHook = (popupId == 'alertPopup')? 'appyAlertText': 'appyConfirmText';
|
||||||
|
@ -715,13 +715,35 @@ function openPopup(popupId, msg) {
|
||||||
// Put it at the right place on the screen
|
// Put it at the right place on the screen
|
||||||
var scrollTop = document.documentElement.scrollTop || window.pageYOffset || 0;
|
var scrollTop = document.documentElement.scrollTop || window.pageYOffset || 0;
|
||||||
popup.style.top = (scrollTop + 150) + 'px';
|
popup.style.top = (scrollTop + 150) + 'px';
|
||||||
|
if (width) popup.style.width = width + 'px';
|
||||||
|
if (popupId == 'iframePopup') {
|
||||||
|
// Initialize iframe's width.
|
||||||
|
var iframe = document.getElementById('appyIFrame');
|
||||||
|
iframe.style.width = (width-20) + 'px';
|
||||||
|
if (height) iframe.style.height = height + 'px';
|
||||||
|
}
|
||||||
popup.style.display = 'block';
|
popup.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
function closePopup(popupId) {
|
function closePopup(popupId) {
|
||||||
// Close the popup
|
// Close the popup
|
||||||
var popup = document.getElementById(popupId);
|
var container = window.parent.document;
|
||||||
|
var popup = container.getElementById(popupId);
|
||||||
popup.style.display = 'none';
|
popup.style.display = 'none';
|
||||||
|
popup.style.width = null;
|
||||||
|
if (popupId == 'iframePopup') {
|
||||||
|
// Reinitialise the enclosing iframe.
|
||||||
|
var iframe = container.getElementById('appyIFrame');
|
||||||
|
iframe.style.width = null;
|
||||||
|
iframe.innerHTML = '';
|
||||||
|
// Leave the form silently if we are on an edit page
|
||||||
|
iframe.contentWindow.onbeforeunload = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function backFromPopup() {
|
||||||
|
closePopup('iframePopup');
|
||||||
|
window.parent.location = window.parent.location;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function triggered when an action needs to be confirmed by the user
|
// Function triggered when an action needs to be confirmed by the user
|
||||||
|
@ -734,8 +756,8 @@ function askConfirm(actionType, action, msg, showComment) {
|
||||||
confirmForm.actionType.value = actionType;
|
confirmForm.actionType.value = actionType;
|
||||||
confirmForm.action.value = action;
|
confirmForm.action.value = action;
|
||||||
var commentArea = document.getElementById('commentArea');
|
var commentArea = document.getElementById('commentArea');
|
||||||
if (showComment) commentArea.style.display = "block";
|
if (showComment) commentArea.style.display = 'block';
|
||||||
else commentArea.style.display = "none";
|
else commentArea.style.display = 'none';
|
||||||
openPopup("confirmActionPopup", msg);
|
openPopup("confirmActionPopup", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,6 +784,12 @@ function doConfirm() {
|
||||||
// We must execute Javascript code in "action"
|
// We must execute Javascript code in "action"
|
||||||
eval(action);
|
eval(action);
|
||||||
}
|
}
|
||||||
|
else if (actionType == 'form+script') {
|
||||||
|
var elems = action.split('+');
|
||||||
|
// Submit the form in elems[0] and execute the JS code in elems[1]
|
||||||
|
document.getElementById(elems[0]).submit();
|
||||||
|
eval(elems[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function triggered when the user asks password reinitialisation
|
// Function triggered when the user asks password reinitialisation
|
||||||
|
@ -952,4 +980,4 @@ function onSelectDate(cal) {
|
||||||
if (update && p.singleClick && cal.dateClicked) {
|
if (update && p.singleClick && cal.dateClicked) {
|
||||||
cal.callCloseHandler();
|
cal.callCloseHandler();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
BIN
gen/ui/close.png
BIN
gen/ui/close.png
Binary file not shown.
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 219 B |
|
@ -176,22 +176,24 @@ class ToolWrapper(AbstractWrapper):
|
||||||
'current' or ''">::_(className + '_plural')</a>
|
'current' or ''">::_(className + '_plural')</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Actions -->
|
<!-- Create instances of this class -->
|
||||||
<x var="mayCreate=ztool.userMayCreate(rootClass);
|
<form if="ztool.userMayCreate(rootClass) and \
|
||||||
createMeans=ztool.getCreateMeans(rootClass)">
|
('form' in ztool.getCreateMeans(rootClass))" class="addForm"
|
||||||
<!-- Create a new object from a web form. -->
|
var2="target=ztool.getLinksTargetInfo(rootClass)"
|
||||||
<input type="button" class="buttonSmall button"
|
action=":'%s/do' % toolUrl" target=":target.target">
|
||||||
if="mayCreate and ('form' in createMeans)"
|
<input type="hidden" name="action" value="Create"/>
|
||||||
var2="label=_('query_create')" value=":label"
|
<input type="hidden" name="className" value=":className"/>
|
||||||
|
<input type="hidden" name="popup"
|
||||||
|
value=":(inPopup or (target.target != '_self')) and '1' or '0'"/>
|
||||||
|
<input type="submit" class="buttonSmall button"
|
||||||
|
var="label=_('query_create')" value=":label"
|
||||||
|
onclick=":target.openPopup"
|
||||||
style=":'%s; %s' % (url('add', bg=True), \
|
style=":'%s; %s' % (url('add', bg=True), \
|
||||||
ztool.getButtonWidth(label))"
|
ztool.getButtonWidth(label))"/>
|
||||||
onclick=":'goto(%s)' % \
|
</form>
|
||||||
q('%s/do?action=Create&className=%s' % \
|
|
||||||
(toolUrl, className))"/>
|
|
||||||
</x>
|
|
||||||
<!-- Searches -->
|
<!-- Searches -->
|
||||||
<x if="ztool.advancedSearchEnabledFor(rootClass)">
|
<x if="ztool.advancedSearchEnabledFor(rootClass)">
|
||||||
|
|
||||||
<!-- Live search -->
|
<!-- Live search -->
|
||||||
<form action=":'%s/do' % toolUrl">
|
<form action=":'%s/do' % toolUrl">
|
||||||
<input type="hidden" name="action" value="SearchObjects"/>
|
<input type="hidden" name="action" value="SearchObjects"/>
|
||||||
|
@ -232,7 +234,8 @@ class ToolWrapper(AbstractWrapper):
|
||||||
|
|
||||||
# The message that is shown when a user triggers an action.
|
# The message that is shown when a user triggers an action.
|
||||||
pxMessage = Px('''
|
pxMessage = Px('''
|
||||||
<div var="messages=ztool.consumeMessages()" if="messages" class="message">
|
<div var="messages=ztool.consumeMessages()" if="messages"
|
||||||
|
class=":inPopup and 'messagePopup message' or 'message'">
|
||||||
<!-- The icon for closing the message -->
|
<!-- The icon for closing the message -->
|
||||||
<img src=":url('close')" align=":dright" class="clickable"
|
<img src=":url('close')" align=":dright" class="clickable"
|
||||||
onclick="this.parentNode.style.display='none'"/>
|
onclick="this.parentNode.style.display='none'"/>
|
||||||
|
@ -308,8 +311,11 @@ class ToolWrapper(AbstractWrapper):
|
||||||
(className, searchName, startNumber+currentNumber, totalNumber);
|
(className, searchName, startNumber+currentNumber, totalNumber);
|
||||||
cssClass=zobj.getCssFor('title')">
|
cssClass=zobj.getCssFor('title')">
|
||||||
<x>::zobj.getSupTitle(navInfo)</x>
|
<x>::zobj.getSupTitle(navInfo)</x>
|
||||||
<a href=":zobj.getUrl(nav=navInfo, page=zobj.getDefaultViewPage())"
|
<a if="enableLinks" class=":cssClass"
|
||||||
if="enableLinks" class=":cssClass">:zobj.Title()</a><span
|
var2="linkInPopup=inPopup or (target.target != '_self')"
|
||||||
|
target=":target.target" onclick=":target.openPopup"
|
||||||
|
href=":zobj.getUrl(nav=navInfo, page=zobj.getDefaultViewPage(), \
|
||||||
|
inPopup=linkInPopup)">:zobj.Title()</a><span
|
||||||
if="not enableLinks" class=":cssClass">:zobj.Title()</span><span
|
if="not enableLinks" class=":cssClass">:zobj.Title()</span><span
|
||||||
style=":showSubTitles and 'display:inline' or 'display:none'"
|
style=":showSubTitles and 'display:inline' or 'display:none'"
|
||||||
name="subTitle">::zobj.getSubTitle()</span>
|
name="subTitle">::zobj.getSubTitle()</span>
|
||||||
|
@ -320,9 +326,11 @@ class ToolWrapper(AbstractWrapper):
|
||||||
<!-- Edit -->
|
<!-- Edit -->
|
||||||
<td if="zobj.mayEdit()">
|
<td if="zobj.mayEdit()">
|
||||||
<a var="navInfo='search.%s.%s.%d.%d' % \
|
<a var="navInfo='search.%s.%s.%d.%d' % \
|
||||||
(className, searchName, loop.zobj.nb+1+startNumber, totalNumber)"
|
(className, searchName, loop.zobj.nb+1+startNumber, totalNumber);
|
||||||
|
linkInPopup=inPopup or (target.target != '_self')"
|
||||||
|
target=":target.target" onclick=":target.openPopup"
|
||||||
href=":zobj.getUrl(mode='edit', page=zobj.getDefaultEditPage(), \
|
href=":zobj.getUrl(mode='edit', page=zobj.getDefaultEditPage(), \
|
||||||
nav=navInfo)">
|
nav=navInfo, inPopup=linkInPopup)">
|
||||||
<img src=":url('edit')" title=":_('object_edit')"/></a>
|
<img src=":url('edit')" title=":_('object_edit')"/></a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -429,7 +437,8 @@ class ToolWrapper(AbstractWrapper):
|
||||||
newSearchUrl='%s/search?className=%s%s' % \
|
newSearchUrl='%s/search?className=%s%s' % \
|
||||||
(ztool.absolute_url(), className, refUrlPart);
|
(ztool.absolute_url(), className, refUrlPart);
|
||||||
showSubTitles=req.get('showSubTitles', 'true') == 'true';
|
showSubTitles=req.get('showSubTitles', 'true') == 'true';
|
||||||
resultMode=ztool.getResultMode(className)">
|
resultMode=ztool.getResultMode(className);
|
||||||
|
target=ztool.getLinksTargetInfo(ztool.getAppyClass(className))">
|
||||||
|
|
||||||
<x if="zobjects">
|
<x if="zobjects">
|
||||||
<!-- Display here POD templates if required. -->
|
<!-- Display here POD templates if required. -->
|
||||||
|
@ -532,6 +541,17 @@ class ToolWrapper(AbstractWrapper):
|
||||||
</form>
|
</form>
|
||||||
</x>''', template=AbstractWrapper.pxTemplate, hook='content')
|
</x>''', template=AbstractWrapper.pxTemplate, hook='content')
|
||||||
|
|
||||||
|
pxBack = Px('''
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src=":ztool.getIncludeUrl('appy.js')" type="text/javascript">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">backFromPopup()</script>
|
||||||
|
</body>
|
||||||
|
</html>''')
|
||||||
|
|
||||||
def isManager(self):
|
def isManager(self):
|
||||||
'''Some pages on the tool can only be accessed by managers.'''
|
'''Some pages on the tool can only be accessed by managers.'''
|
||||||
if self.user.has_role('Manager'): return 'view'
|
if self.user.has_role('Manager'): return 'view'
|
||||||
|
|
|
@ -21,9 +21,9 @@ class AbstractWrapper(object):
|
||||||
# Buttons for going to next/previous objects if this one is among bunch of
|
# Buttons for going to next/previous objects if this one is among bunch of
|
||||||
# referenced or searched objects. currentNumber starts with 1.
|
# referenced or searched objects. currentNumber starts with 1.
|
||||||
pxNavigateSiblings = Px('''
|
pxNavigateSiblings = Px('''
|
||||||
<div if="req.get('nav', None)" var2="ni=ztool.getNavigationInfo()">
|
<div if="req.get('nav', None)" var2="ni=ztool.getNavigationInfo(inPopup)">
|
||||||
<!-- Go to the source URL (search or referred object) -->
|
<!-- Go to the source URL (search or referred object) -->
|
||||||
<a if="ni.sourceUrl" href=":ni.sourceUrl"><img
|
<a if="not inPopup and ni.sourceUrl" href=":ni.sourceUrl"><img
|
||||||
var="gotoSource=_('goto_source');
|
var="gotoSource=_('goto_source');
|
||||||
goBack=ni.backText and ('%s - %s' % (ni.backText, gotoSource)) \
|
goBack=ni.backText and ('%s - %s' % (ni.backText, gotoSource)) \
|
||||||
or gotoSource"
|
or gotoSource"
|
||||||
|
@ -52,7 +52,7 @@ class AbstractWrapper(object):
|
||||||
<tr>
|
<tr>
|
||||||
<!-- Breadcrumb -->
|
<!-- Breadcrumb -->
|
||||||
<td var="sup=zobj.getSupBreadCrumb();
|
<td var="sup=zobj.getSupBreadCrumb();
|
||||||
breadcrumb=zobj.getBreadCrumb();
|
breadcrumb=zobj.getBreadCrumb(inPopup=inPopup);
|
||||||
sub=zobj.getSubBreadCrumb()" class="breadcrumb">
|
sub=zobj.getSubBreadCrumb()" class="breadcrumb">
|
||||||
<x if="sup">::sup</x>
|
<x if="sup">::sup</x>
|
||||||
<x for="bc in breadcrumb" var2="nb=loop.bc.nb">
|
<x for="bc in breadcrumb" var2="nb=loop.bc.nb">
|
||||||
|
@ -84,7 +84,8 @@ class AbstractWrapper(object):
|
||||||
dummy=setattr(req, 'pxContext', _ctx_);
|
dummy=setattr(req, 'pxContext', _ctx_);
|
||||||
lang=ztool.getUserLanguage(); q=ztool.quote;
|
lang=ztool.getUserLanguage(); q=ztool.quote;
|
||||||
layoutType=ztool.getLayoutType();
|
layoutType=ztool.getLayoutType();
|
||||||
showPortlet=ztool.showPortlet(obj, layoutType);
|
inPopup=req.get('popup') == '1';
|
||||||
|
showPortlet=not inPopup and ztool.showPortlet(obj, layoutType);
|
||||||
dir=ztool.getLanguageDirection(lang);
|
dir=ztool.getLanguageDirection(lang);
|
||||||
cfg=ztool.getProductConfig(True);
|
cfg=ztool.getProductConfig(True);
|
||||||
dleft=(dir == 'ltr') and 'left' or 'right';
|
dleft=(dir == 'ltr') and 'left' or 'right';
|
||||||
|
@ -170,9 +171,17 @@ class AbstractWrapper(object):
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Popup containing the Appy iframe -->
|
||||||
|
<div id="iframePopup" class="popup" if="not inPopup"
|
||||||
|
style="background-color: #fbfbfb">
|
||||||
|
<img align=":dright" src=":url('close')" class="clickable"
|
||||||
|
onclick="closePopup('iframePopup')"/>
|
||||||
|
<iframe id="appyIFrame" name="appyIFrame" frameborder="0"></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
<table class=":(cfg.skin == 'wide') and 'mainWide main' or 'main'"
|
<table class=":(cfg.skin == 'wide') and 'mainWide main' or 'main'"
|
||||||
align="center" cellpadding="0">
|
align="center" cellpadding="0">
|
||||||
<tr class="top">
|
<tr class="top" if="not inPopup">
|
||||||
<!-- Top banner -->
|
<!-- Top banner -->
|
||||||
<td var="bannerName=(dir == 'ltr') and 'banner' or 'bannerrtl'"
|
<td var="bannerName=(dir == 'ltr') and 'banner' or 'bannerrtl'"
|
||||||
style=":url(bannerName, bg=True) + '; background-repeat:no-repeat;\
|
style=":url(bannerName, bg=True) + '; background-repeat:no-repeat;\
|
||||||
|
@ -213,7 +222,7 @@ class AbstractWrapper(object):
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<!-- The user strip -->
|
<!-- The user strip -->
|
||||||
<tr height=":cfg.discreetLogin and '5px' or '28px'">
|
<tr height=":cfg.discreetLogin and '5px' or '28px'" if="not inPopup">
|
||||||
<td>
|
<td>
|
||||||
<table class="userStrip">
|
<table class="userStrip">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -297,7 +306,7 @@ class AbstractWrapper(object):
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<tr height="26px"><td>:tool.pxFooter</td></tr>
|
<tr height="26px" if="not inPopup"><td>:tool.pxFooter</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>''', prologue=Px.xhtmlPrologue)
|
</html>''', prologue=Px.xhtmlPrologue)
|
||||||
|
@ -401,7 +410,7 @@ class AbstractWrapper(object):
|
||||||
historyMaxPerPage=req.get('maxPerPage', 5);
|
historyMaxPerPage=req.get('maxPerPage', 5);
|
||||||
historyExpanded=req.get('appyHistory','collapsed')=='expanded';
|
historyExpanded=req.get('appyHistory','collapsed')=='expanded';
|
||||||
creator=zobj.Creator()">
|
creator=zobj.Creator()">
|
||||||
<table width="100%" class="summary">
|
<table width="100%" class="summary" cellpadding="0" cellspacing="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" class="by">
|
<td colspan="2" class="by">
|
||||||
<!-- Plus/minus icon for accessing history -->
|
<!-- Plus/minus icon for accessing history -->
|
||||||
|
@ -461,7 +470,8 @@ class AbstractWrapper(object):
|
||||||
<tr valign="top">
|
<tr valign="top">
|
||||||
<!-- 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', \
|
||||||
|
inPopup=inPopup)">
|
||||||
<img title="Refresh" style="vertical-align:top" src=":url('refresh')"/>
|
<img title="Refresh" style="vertical-align:top" src=":url('refresh')"/>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -479,7 +489,8 @@ class AbstractWrapper(object):
|
||||||
<!-- Button on the view page -->
|
<!-- Button on the view page -->
|
||||||
<input if="not isEdit" type="button" class="button" value=":label"
|
<input if="not isEdit" type="button" class="button" value=":label"
|
||||||
style=":'%s; %s' % (url('previous', bg=True), buttonWidth)"
|
style=":'%s; %s' % (url('previous', bg=True), buttonWidth)"
|
||||||
onclick=":'goto(%s)' % q(zobj.getUrl(page=previousPage))"/>
|
onclick=":'goto(%s)' % q(zobj.getUrl(page=previousPage, \
|
||||||
|
inPopup=inPopup))"/>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- Save -->
|
<!-- Save -->
|
||||||
|
@ -506,7 +517,8 @@ class AbstractWrapper(object):
|
||||||
var="label=_('object_edit')" value=":label"
|
var="label=_('object_edit')" value=":label"
|
||||||
style=":'%s; %s' % (url('edit', bg=True), \
|
style=":'%s; %s' % (url('edit', bg=True), \
|
||||||
ztool.getButtonWidth(label))"
|
ztool.getButtonWidth(label))"
|
||||||
onclick=":'goto(%s)' % q(zobj.getUrl(mode='edit', page=page))"/>
|
onclick=":'goto(%s)' % q(zobj.getUrl(mode='edit', page=page, \
|
||||||
|
inPopup=inPopup))"/>
|
||||||
|
|
||||||
<!-- Locked -->
|
<!-- Locked -->
|
||||||
<a if="editable and locked">
|
<a if="editable and locked">
|
||||||
|
@ -536,7 +548,8 @@ class AbstractWrapper(object):
|
||||||
<!-- Button on the view page -->
|
<!-- Button on the view page -->
|
||||||
<input if="not isEdit" type="button" class="button" value=":label"
|
<input if="not isEdit" type="button" class="button" value=":label"
|
||||||
style=":'%s; %s' % (url('next', bg=True), buttonWidth)"
|
style=":'%s; %s' % (url('next', bg=True), buttonWidth)"
|
||||||
onclick=":'goto(%s)' % q(zobj.getUrl(page=nextPage))"/>
|
onclick=":'goto(%s)' % q(zobj.getUrl(page=nextPage, \
|
||||||
|
inPopup=inPopup))"/>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- Workflow transitions -->
|
<!-- Workflow transitions -->
|
||||||
|
@ -590,6 +603,7 @@ class AbstractWrapper(object):
|
||||||
enctype="multipart/form-data" action=":zobj.absolute_url()+'/do'">
|
enctype="multipart/form-data" action=":zobj.absolute_url()+'/do'">
|
||||||
<input type="hidden" name="action" value="Update"/>
|
<input type="hidden" name="action" value="Update"/>
|
||||||
<input type="hidden" name="button" value=""/>
|
<input type="hidden" name="button" value=""/>
|
||||||
|
<input type="hidden" name="popup" value=":inPopup and '1' or '0'"/>
|
||||||
<input type="hidden" name="page" value=":page"/>
|
<input type="hidden" name="page" value=":page"/>
|
||||||
<input type="hidden" name="nav" value=":req.get('nav', None)"/>
|
<input type="hidden" name="nav" value=":req.get('nav', None)"/>
|
||||||
<input type="hidden" name="confirmed" value="False"/>
|
<input type="hidden" name="confirmed" value="False"/>
|
||||||
|
@ -615,6 +629,7 @@ class AbstractWrapper(object):
|
||||||
lang=ztool.getUserLanguage(); q=ztool.quote;
|
lang=ztool.getUserLanguage(); q=ztool.quote;
|
||||||
action=req.get('action', None);
|
action=req.get('action', None);
|
||||||
px=req['px'].split(':');
|
px=req['px'].split(':');
|
||||||
|
inPopup=req.get('popup') == '1';
|
||||||
className=(len(px) == 3) and px[0] or None;
|
className=(len(px) == 3) and px[0] or None;
|
||||||
field=className and zobj.getAppyType(px[1], className) or None;
|
field=className and zobj.getAppyType(px[1], className) or None;
|
||||||
field=(len(px) == 2) and zobj.getAppyType(px[0]) or field;
|
field=(len(px) == 2) and zobj.getAppyType(px[0]) or field;
|
||||||
|
|
Loading…
Reference in a new issue