[gen] Ergonomic improvements: added a breadcrumb, more compact design.
This commit is contained in:
parent
3ec1270fc2
commit
387fbaea7c
|
@ -1172,9 +1172,8 @@ class String(Type):
|
|||
# Default width, height and maxChars vary according to String format
|
||||
if width == None:
|
||||
if format == String.TEXT: self.width = 60
|
||||
# This width corresponds to the standard width of an Appy page,
|
||||
# minus the portlet.
|
||||
if format == String.XHTML: self.width = 750
|
||||
# This width corresponds to the standard width of an Appy page.
|
||||
if format == String.XHTML: self.width = 870
|
||||
else: self.width = 30
|
||||
if height == None:
|
||||
if format == String.TEXT: self.height = 5
|
||||
|
|
|
@ -217,13 +217,13 @@ class Table(LayoutElement):
|
|||
# Some base layouts to use, for fields and pages -------------------------------
|
||||
# The default layouts for pages
|
||||
defaultPageLayouts = {
|
||||
'view': Table('n!-w|-b|', align="center"),
|
||||
'view': Table('w|-b|', align="center"),
|
||||
'edit': Table('w|-b|', width=None)}
|
||||
# A layout for pages, containing the page summary.
|
||||
summaryPageLayouts = {'view': Table('s-n!-w|-b|', align="center"),
|
||||
summaryPageLayouts = {'view': Table('s-w|-b|', align="center"),
|
||||
'edit': Table('w|-b|', width=None)}
|
||||
widePageLayouts = {
|
||||
'view': Table('n!-w|-b|', align="center"),
|
||||
'view': Table('w|-b|', align="center"),
|
||||
'edit': Table('w|-b|')
|
||||
}
|
||||
# The default layout for fields. Alternative layouts may exist and are declared
|
||||
|
|
|
@ -245,7 +245,10 @@ class ToolMixin(BaseMixin):
|
|||
elems = sortMethod(elems)
|
||||
return [importParams['headers'], elems]
|
||||
|
||||
def showPortlet(self, context):
|
||||
def showPortlet(self, context, layoutType):
|
||||
'''When must the portlet be shown?'''
|
||||
# Not on 'edit' pages.
|
||||
if layoutType == 'edit': return
|
||||
if context.id == 'ui': context = context.getParentNode()
|
||||
res = True
|
||||
if hasattr(context.aq_base, 'appy'):
|
||||
|
@ -424,15 +427,27 @@ class ToolMixin(BaseMixin):
|
|||
return '<acronym title="%s">%s</acronym>' % \
|
||||
(text, uText[:width].encode('utf-8') + '...')
|
||||
|
||||
def getPublishedObject(self):
|
||||
def getLayoutType(self):
|
||||
'''Guess the current layout type, according to actual URL.'''
|
||||
actualUrl = self.REQUEST['ACTUAL_URL']
|
||||
res = ''
|
||||
if actualUrl.endswith('/ui/view'):
|
||||
res = 'view'
|
||||
elif actualUrl.endswith('/ui/edit') or actualUrl.endswith('/do'):
|
||||
res = 'edit'
|
||||
return res
|
||||
|
||||
def getPublishedObject(self, layoutType):
|
||||
'''Gets the currently published object, if its meta_class is among
|
||||
application classes.'''
|
||||
req = self.REQUEST
|
||||
# If we are querying object, there is no published object (the truth is:
|
||||
# the tool is the currently published object but we don't want to
|
||||
# consider it this way).
|
||||
if not req['ACTUAL_URL'].endswith('/ui/view'): return
|
||||
# In some situations (ie, we are querying objects), the published object
|
||||
# according to Zope is the tool, but we don't want to consider it that
|
||||
# way.
|
||||
if layoutType not in ('edit', 'view'): return
|
||||
obj = self.REQUEST['PUBLISHED']
|
||||
# If URL is a /do, published object is the "do" method.
|
||||
if type(obj) == types.MethodType: obj = obj.im_self
|
||||
else:
|
||||
parent = obj.getParentNode()
|
||||
if parent.id == 'ui': obj = parent.getParentNode()
|
||||
if obj.meta_type in self.getProductConfig().attributes: return obj
|
||||
|
|
|
@ -822,6 +822,11 @@ class BaseMixin:
|
|||
break
|
||||
return phase
|
||||
else:
|
||||
# Return an empty list if we have a single, link-free page within
|
||||
# a single phase.
|
||||
if (len(res) == 1) and (len(res[0]['pages']) == 1) and \
|
||||
not res[0]['pagesInfo'][res[0]['pages'][0]].get('links'):
|
||||
return None
|
||||
return res
|
||||
|
||||
def getIcons(self):
|
||||
|
@ -1434,7 +1439,16 @@ class BaseMixin:
|
|||
# Not-Managers can't navigate back to the tool
|
||||
if (parent.id == 'config') and not self.getUser().has_role('Manager'):
|
||||
return False
|
||||
if parent.meta_type != 'Folder': return parent
|
||||
if parent.meta_type not in ('Folder', 'Temporary Folder'): return parent
|
||||
|
||||
def getBreadCrumb(self):
|
||||
'''Gets breadcrumb info about this object and its parents.'''
|
||||
res = [{'url': self.absolute_url(),
|
||||
'title': self.getFieldValue('title', layoutType='view')}]
|
||||
parent = self.getParent()
|
||||
if parent:
|
||||
res = parent.getBreadCrumb() + res
|
||||
return res
|
||||
|
||||
def index_html(self):
|
||||
'''Redirects to /ui.'''
|
||||
|
|
|
@ -57,6 +57,9 @@ img { border: 0; vertical-align: middle}
|
|||
.userStripText { font-size: 110%; padding: 0 0.3em 0 0.3em; color: white }
|
||||
.userStrip a { color: #e7e7e7 }
|
||||
.userStrip a:visited { color: #e7e7e7 }
|
||||
.navigate { border-bottom: 1px solid #5F7983;
|
||||
background-color: #dbdde1; font-weight: bold }
|
||||
.navigate td { padding: 4px 9px }
|
||||
.login { margin-top: 2px; margin-bottom: 2px; color: black;}
|
||||
.buttons { margin-left: 4px;}
|
||||
.fakeButton { border: 1px solid #D7DEE4; background-color: #fde8e0;
|
||||
|
@ -73,7 +76,7 @@ img { border: 0; vertical-align: middle}
|
|||
.lostPassword a { font-size: 90%; color: white; padding-left: 1em;}
|
||||
.portlet { width: 150px; border-right: 1px solid #5F7983;
|
||||
background-color: #ededed}
|
||||
.portletContent { margin: 9px; }
|
||||
.portletContent { margin: 4px 9px }
|
||||
.portletTitle { font-weight: bold; font-size: 110%; margin-bottom: 4px;}
|
||||
.portletCurrent { font-weight: bold; }
|
||||
.portletSep { border-top: 1px solid #5F7983; margin-top: 2px;}
|
||||
|
@ -113,21 +116,20 @@ img { border: 0; vertical-align: middle}
|
|||
text-align: center; color: white; }
|
||||
.odd { background-color: #f9f9f9; }
|
||||
.even { background-color: #f4f4f4; }
|
||||
.summary {margin-bottom: 5px;}
|
||||
.summary { margin-bottom: 5px; background-color: #e9e9e9;
|
||||
border: 1px dashed grey }
|
||||
.objectTitle { font-size: 11pt; border-bottom: 3px solid grey;
|
||||
font-weight: bold;}
|
||||
.by { padding-top: 5px; color: grey; font-size: 97% }
|
||||
.underTitle { background-color: #e9e9e9 }
|
||||
.objectNavigate { margin-top: 3px;}
|
||||
.by { padding: 5px; color: grey; font-size: 97% }
|
||||
.underline { border-bottom: 1px dotted grey;}
|
||||
.state { font-weight: bold; border-bottom: 1px dashed grey;}
|
||||
.historyLabel { font-variant: small-caps; font-weight: bold;}
|
||||
.history td { border-top: 1px solid grey;}
|
||||
.history th { font-style: italic; text-align; left;}
|
||||
.history td { border-top: 1px solid grey; padding: 0 5px 0 5px }
|
||||
.history th { font-style: italic; text-align: left; padding: 0 5px 0 5px }
|
||||
.topSpace { margin-top: 15px;}
|
||||
.bottomSpace { margin-bottom: 15px;}
|
||||
.discreet { color: grey}
|
||||
.pageLink { padding-left: 6px; font-style: italic}
|
||||
.pageLink { padding-left: 8px }
|
||||
.footer { font-size: 95% }
|
||||
.footer td { background-color: #CBCBC9; border-top: 1px solid grey;
|
||||
padding: 0.4em 1em 0.5em }
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
<tal:main define="tool context/getTool">
|
||||
<html metal:use-macro="context/ui/template/macros/main">
|
||||
<metal:fill fill-slot="content"
|
||||
tal:define="contextObj context/getParentNode;
|
||||
dummy python: contextObj.allows('Modify portal content', raiseError=True);
|
||||
tal:define="dummy python: contextObj.allows('Modify portal content', raiseError=True);
|
||||
errors request/errors | python:{};
|
||||
layoutType python:'edit';
|
||||
layout python: contextObj.getPageLayout(layoutType);
|
||||
cssJs python: {};
|
||||
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType=layoutType);
|
||||
|
|
|
@ -46,13 +46,12 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<div metal:define-macro="objectNavigate" tal:condition="request/nav|nothing">
|
||||
<tal:comment replace="nothing">
|
||||
<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>
|
||||
<table class="objectNavigate"
|
||||
tal:define="navInfo tool/getNavigationInfo;
|
||||
</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;
|
||||
|
@ -61,36 +60,56 @@
|
|||
lastUrl navInfo/lastUrl;
|
||||
sourceUrl navInfo/sourceUrl;
|
||||
backText navInfo/backText">
|
||||
<tr valign="middle">
|
||||
<tal:comment replace="nothing">Go to the source URL (search or referred object)</tal:comment>
|
||||
<td tal:condition="sourceUrl"><a tal:attributes="href sourceUrl"><img
|
||||
<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></td>
|
||||
tal:attributes="src string: $appUrl/ui/gotoSource.png; title goBack"/></a>
|
||||
<tal:comment replace="nothing">Go to the first page</tal:comment>
|
||||
<td tal:condition="firstUrl"><a tal:attributes="href firstUrl"><img
|
||||
<a tal:condition="firstUrl" tal:attributes="href firstUrl"><img
|
||||
tal:attributes="src string: $appUrl/ui/arrowLeftDouble.png;
|
||||
title python: _('goto_first')"/></a></td>
|
||||
title python: _('goto_first')"/></a>
|
||||
<tal:comment replace="nothing">Go to the previous page</tal:comment>
|
||||
<td tal:condition="previousUrl"><a tal:attributes="href previousUrl"><img
|
||||
<a tal:condition="previousUrl" tal:attributes="href previousUrl"><img
|
||||
tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png;
|
||||
title python: _('goto_previous')"/></a></td>
|
||||
title python: _('goto_previous')"/></a>
|
||||
<tal:comment replace="nothing">Explain which element is currently shown</tal:comment>
|
||||
<td class="discreet">
|
||||
<span class="discreet">
|
||||
<span tal:replace="python: currentNumber"/> <b>//</b>
|
||||
<span tal:replace="python: totalNumber"/>
|
||||
</td>
|
||||
</span>
|
||||
<tal:comment replace="nothing">Go to the next page</tal:comment>
|
||||
<td tal:condition="python: nextUrl"><a tal:attributes="href nextUrl"><img
|
||||
<a tal:condition="python: nextUrl" tal:attributes="href nextUrl"><img
|
||||
tal:attributes="src string: $appUrl/ui/arrowRightSimple.png;
|
||||
title python: _('goto_next')"/></a></td>
|
||||
title python: _('goto_next')"/></a>
|
||||
<tal:comment replace="nothing">Go to the last page</tal:comment>
|
||||
<td tal:condition="lastUrl"><a tal:attributes="href lastUrl"><img
|
||||
<a tal:condition="lastUrl" tal:attributes="href lastUrl"><img
|
||||
tal:attributes="src string: $appUrl/ui/arrowRightDouble.png;
|
||||
title python: _('goto_last')"/></a></td>
|
||||
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">
|
||||
<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>
|
||||
</div>
|
||||
</table>
|
||||
|
||||
<tal:comment replace="nothing">
|
||||
This macro displays up/down arrows in a table header column for sorting a given column.
|
||||
|
|
|
@ -183,14 +183,8 @@
|
|||
<tal:comment replace="nothing">Information that is common to all tabs (object title, state, etc)</tal:comment>
|
||||
<table width="100%" class="summary">
|
||||
<tr>
|
||||
<tal:comment replace="nothing">Title</tal:comment>
|
||||
<td colspan="2" class="objectTitle">
|
||||
<tal:icons replace="structure contextObj/getIcons"/>
|
||||
<span tal:content="python: contextObj.getFieldValue('title', layoutType='view')"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="underTitle">
|
||||
<td colspan="2" class="by">
|
||||
<tal:icons replace="structure contextObj/getIcons"/>
|
||||
<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">
|
||||
|
@ -225,7 +219,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tal:comment replace="nothing">Object history</tal:comment>
|
||||
<tr tal:condition="hasHistory" class="underTitle">
|
||||
<tr tal:condition="hasHistory">
|
||||
<td colspan="2">
|
||||
<span id="appyHistory"
|
||||
tal:attributes="style python:test(historyExpanded, 'display:block', 'display:none')">
|
||||
|
|
|
@ -50,25 +50,19 @@
|
|||
appUrl app/absolute_url;
|
||||
currentSearch req/search|nothing;
|
||||
currentClass req/className|nothing;
|
||||
contextObj tool/getPublishedObject;
|
||||
rootClasses tool/getRootClasses">
|
||||
rootClasses tool/getRootClasses;
|
||||
phases python: contextObj and contextObj.getAppyPhases() or None">
|
||||
|
||||
<div class="portletContent" tal:condition="python: contextObj and contextObj.mayNavigate()">
|
||||
<div class="portletTitle" tal:define="parent contextObj/getParent">
|
||||
<span tal:replace="contextObj/Title"></span>
|
||||
<a tal:condition="python: parent" tal:attributes="href parent/absolute_url">
|
||||
<img tal:attributes="src string: $appUrl/ui/gotoSource.png"/>
|
||||
</a>
|
||||
</div>
|
||||
<tal:phases condition="python: contextObj and phases and contextObj.mayNavigate()">
|
||||
<metal:phases use-macro="app/ui/portlet/macros/phases"/>
|
||||
</div>
|
||||
</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 and contextObj) or (nb != 1)"></div>
|
||||
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), with action icons</tal:comment>
|
||||
|
@ -119,9 +113,8 @@
|
|||
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"
|
||||
tal:define="phases contextObj/getAppyPhases;
|
||||
singlePhase python: len(phases) == 1;
|
||||
<table metal:define-macro="phases" class="portletContent"
|
||||
tal:define="singlePhase python: phases and (len(phases) == 1);
|
||||
page python: req.get('page', 'main')">
|
||||
<tal:phase repeat="phase phases">
|
||||
<tal:comment replace="nothing">The box containing phase-related information</tal:comment>
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
req python: request;
|
||||
resp req/RESPONSE;
|
||||
lang tool/getUserLanguage;
|
||||
layoutType tool/getLayoutType;
|
||||
contextObj python: tool.getPublishedObject(layoutType);
|
||||
dir python: tool.getLanguageDirection(lang);
|
||||
dleft python: (dir == 'ltr') and 'left' or 'right';
|
||||
dright python: (dir == 'ltr') and 'right' or 'left';
|
||||
|
@ -35,7 +37,7 @@
|
|||
<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)">
|
||||
<table width="100%">
|
||||
<table width="100%" style="margin-top: 4px">
|
||||
<tr valign="top" tal:define="pages tool/getMainPages">
|
||||
<tal:comment replace="nothing">Links to main pages</tal:comment>
|
||||
<td tal:condition="pages"><a tal:repeat="page pages" class="pageLink"
|
||||
|
@ -183,12 +185,16 @@
|
|||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tal:comment replace="nothing">The navigation strip</tal:comment>
|
||||
<tr tal:condition="python: contextObj and (layoutType == 'view')">
|
||||
<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="python: tool.showPortlet(context)" class="portlet">
|
||||
<td tal:condition="python: tool.showPortlet(context, layoutType)" class="portlet">
|
||||
<metal:portlet use-macro="app/ui/portlet/macros/portlet"/>
|
||||
</td>
|
||||
<tal:comment replace="nothing">Page content</tal:comment>
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
<tal:main define="tool context/config">
|
||||
<html metal:use-macro="context/ui/template/macros/main">
|
||||
<metal:fill fill-slot="content"
|
||||
tal:define="contextObj python: context.getParentNode();
|
||||
dummy python: contextObj.allows('View', raiseError=True);
|
||||
tal:define="dummy python: contextObj.allows('View', raiseError=True);
|
||||
errors python: req.get('errors', {});
|
||||
layoutType python:'view';
|
||||
layout python: contextObj.getPageLayout(layoutType);
|
||||
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
|
||||
phase phaseInfo/name;
|
||||
|
|
Loading…
Reference in a new issue