merge branch master

This commit is contained in:
Helmut Merz 2012-07-03 13:15:54 +02:00
commit 54c3a9e8aa
20 changed files with 913 additions and 43 deletions

View file

@ -130,6 +130,7 @@ class EditForm(form.EditForm):
class BaseView(GenericView, I18NView):
actions = {}
portlet_actions = []
icon = None
modeName = 'view'
isToplevel = False

View file

@ -243,9 +243,13 @@ class ConceptView(BaseView):
if self.breadcrumbsParent is not None:
data.extend(self.breadcrumbsParent.breadcrumbs())
if self.context != self.nodeView.targetObject:
data.append(dict(label=self.title, url=self.targetUrl))
data.append(dict(label=self.breadcrumbsTitle, url=self.targetUrl))
return data
@Lazy
def breadcrumbsTitle(self):
return self.title
@Lazy
def breadcrumbsParent(self):
return None
@ -503,6 +507,12 @@ class ConceptView(BaseView):
acts.extend(self.actions[category](self, page, target))
return acts
def getPortletActions(self, page=None, target=None):
if self.portlet_actions:
return actions.get('portlet', self.portlet_actions,
view=self, page=page, target=target)
return []
def getObjectActions(self, page=None, target=None):
acts = ['info']
if self.globalOptions('organize.allowSendEmail'):
@ -510,7 +520,7 @@ class ConceptView(BaseView):
acts.extend('state.' + st.statesDefinition for st in self.states)
return actions.get('object', acts, view=self, page=page, target=target)
actions = dict(object=getObjectActions)
actions = dict(object=getObjectActions, portlet=getPortletActions)
def checkAction(self, name, category, target):
if name in (self.typeOptions('hide_action.' + category) or []):

View file

@ -27,10 +27,19 @@
<tal:actions condition="view/showObjectActions">
<div metal:use-macro="views/node_macros/object_actions" />
</tal:actions>
<h1 tal:attributes="ondblclick item/openEditWindow">
<h1 tal:define="tabview item/tabview|nothing"
tal:attributes="ondblclick item/openEditWindow">
<a tal:omit-tag="python: level > 1"
tal:attributes="href request/URL"
tal:content="item/title">Title</a>
<a title="Show tabular view"
i18n:attributes="title"
tal:condition="tabview"
tal:attributes="href
string:${item/targetUrl}?loops.viewName=$tabview">
<img tal:attributes="src
string:$resourceBase/cybertools.icons/table.png" />
</a>
</h1>
</metal:title>
<p tal:define="description description|item/renderedDescription"

View file

@ -501,6 +501,9 @@ class EditObject(FormController, I18NView):
@Lazy
def target(self):
targetUid = self.request.form.get('targetUid')
if targetUid:
return self.view.getObjectForUid(targetUid)
return self.view.virtualTargetObject or self.context
@Lazy
@ -706,8 +709,7 @@ class CreateObject(EditObject):
obj.setType(self.objectType)
notify(ObjectCreatedEvent(obj))
#notify(ObjectAddedEvent(obj))
self.object = obj
# TODO: validate fields
self.object = self.view.object = obj
formState = self.updateFields() # TODO: suppress validation
self.view.formState = formState
# TODO: error handling

View file

@ -19,7 +19,9 @@
<input type="hidden" name="form.action" value="edit"
tal:attributes="value view/form_action" />
<input type="hidden" name="version"
tal:attributes="value request/version | nothing" />
tal:attributes="value request/version|nothing" />
<input type="hidden" name="targetUid"
tal:attributes="value request/targetUid|nothing" />
<tal:title condition="not:view/isInnerHtml">
<h1 tal:content="request/view_title|view/title"
i18n:translate="">Edit Information Object</h1>

View file

@ -240,6 +240,27 @@
</metal:actions>
<metal:breadcrumbs define-macro="breadcrumbs">
<table class="breadcrumbs"
tal:define="crumbs view/breadcrumbs"
tal:condition="crumbs">
<tr>
<td style="white-space: nowrap; vertical-align: top; width: 10%"
i18n:translate="">You are here:</td>
<td>
<span>
<span style="white-space: nowrap"
tal:repeat="crumb crumbs">
<a tal:attributes="href crumb/url"
tal:content="crumb/label" />
<tal:delimiter
condition="not:repeat/crumb/end"> ></tal:delimiter></span> </span>
</td>
</tr>
</table>
</metal:breadcrumbs>
<metal:actions define-macro="view_modes">
<ul class="view-modes"
tal:define="viewModes view/viewModes"

View file

@ -227,6 +227,15 @@ class ResourceView(BaseView):
response.setHeader('Last-Modified', modified.strftime(format))
return data
def render(self):
""" Return the rendered content (data) of the context object.
"""
self.recordAccess('render', target=self.uniqueId)
ctx = adapted(self.context)
text = ctx.data
contentType = ctx.contentType
return self.renderText(ctx.data, ctx.contentType)
def renderText(self, text, contentType):
if contentType == 'text/restructured' and wikiLinksActive(self.loopsRoot):
# TODO: make this more flexible/configurable
@ -400,15 +409,6 @@ class DocumentView(ResourceView):
@Lazy
def view(self): return self
def render(self):
""" Return the rendered content (data) of the context object.
"""
self.recordAccess('render', target=self.uniqueId)
ctx = adapted(self.context)
text = ctx.data
contentType = ctx.contentType
return self.renderText(ctx.data, ctx.contentType)
@Lazy
def inlineEditable(self):
return (self.inlineEditingActive

View file

@ -83,8 +83,8 @@
</span>
<span class="button"
tal:condition="item/xeditable">
<a title="Edit with External Editor"
i18n:translate=""
<a title="Edit with external editor"
i18n:translate="" i18n:attributes="title"
tal:define="url view/virtualTargetUrl"
tal:attributes="href string:$url/external_edit?version=this">
Open for editing

View file

@ -6,6 +6,10 @@ from cybertools.browser.liquid import Liquid
from cybertools.browser.blue import Blue
class Loopy(Liquid):
""" The Loopy (neutral enduser) skin with all portlets on the
left-hand side """
class Loopz(Liquid):
""" The Loopz (neutral enduser) skin """

View file

@ -5,6 +5,28 @@
xmlns="http://namespaces.zope.org/browser"
i18n_domain="loops">
<!-- Loopy skin -->
<zope:interface
interface="loops.browser.skin.Loopy"
type="zope.publisher.interfaces.browser.IBrowserSkinType"
name="Loopy" />
<page for="*"
name="body.html"
class="loops.browser.skin.loopy.browser.View"
permission="zope.View"
layer="loops.browser.skin.Loopy" />
<resource name="loops.css" file="loopy/loops.css"
layer="loops.browser.skin.Loopy" />
<resource name="custom.css" file="loopy/custom.css"
layer="loops.browser.skin.Loopy" />
<resource name="favicon.png" file="loops_favicon.png"
layer="loops.browser.skin.Loopy" />
<resource name="logo.png" file="loops_logo.png"
layer="loops.browser.skin.Loopy" />
<!-- Loopz skin -->
<zope:interface

View file

@ -27,23 +27,7 @@
<div id="content" class="span-6"
metal:define-macro="content">
<metal:breadcrumbs define-slot="breadcrumbs">
<table class="breadcrumbs"
tal:define="crumbs view/breadcrumbs"
tal:condition="crumbs">
<tr>
<td style="white-space: nowrap; vertical-align: top; width: 10%"
i18n:translate="">You are here:</td>
<td>
<span>
<span style="white-space: nowrap"
tal:repeat="crumb crumbs">
<a tal:attributes="href crumb/url"
tal:content="crumb/label" />
<tal:delimiter
condition="not:repeat/crumb/end"> ></tal:delimiter></span> </span>
</td>
</tr>
</table>
<metal:tabs use-macro="views/node_macros/breadcrumbs" />
</metal:breadcrumbs>
<div metal:define-slot="actions"></div>
<div metal:define-slot="message"></div>

View file

@ -0,0 +1,4 @@
# package loops.browser.skin.loopy
#
# variant of the Loopz skin with all portlets on the left
#

View file

@ -0,0 +1,51 @@
<tal:block i18n:domain="loops">
<div metal:use-macro="views/cybertools.body_macros/body">
<a href="#" name="top" metal:fill-slot="logo"
tal:attributes="href view/topMenu/url"><img
src="logo.png" border="0"
alt="loops Site"
tal:attributes="src string:${resourceBase}logo.png" /></a>
<metal:breadcrumbs fill-slot="breadcrumbs">
<metal:tabs use-macro="views/node_macros/breadcrumbs" />
</metal:breadcrumbs>
<metal:tabs fill-slot="view_modes">
<metal:tabs use-macro="views/node_macros/view_modes" />
</metal:tabs>
<metal:left fill-slot="portlet-left">
<tal:portlet repeat="macro controller/macros/portlet_left">
<metal:portlet use-macro="macro" />
</tal:portlet>
<tal:portlet repeat="macro controller/macros/portlet_right">
<metal:portlet use-macro="macro" />
</tal:portlet>
</metal:left>
<metal:right fill-slot="portlet-right" />
<metal:footer fill-slot="footer">
<div xtal:condition="view/editable"
tal:condition="nothing">
<span i18n:translate="">For quick creation of notes/links bookmark this link</span>:
<a href="#"
tal:attributes="href view/popupCreateObjectForm">Create loops Note</a>
</div>
Powered by
<b><a href="http://loops.cy55.de">loops</a></b> &middot;
<b><a href="http://wiki.zope.org/zope3">Zope 3</a></b> &middot;
<b><a href="http://www.python.org">Python</a></b> &middot;
<b><a href="http://www.dojotoolkit.org">Dojo</a></b>.
</metal:footer>
</div>
</tal:block>

View file

@ -0,0 +1,29 @@
#
# Copyright (c) 2012 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Dummy view class for providing the body template.
"""
from cybertools.browser.view import UnboundTemplateFile
class View(object):
bodyTemplate = UnboundTemplateFile('body.pt')

View file

@ -0,0 +1,33 @@
/*
custom.css
*/
body {
color: #242424;
}
a {
text-decoration: none;
color: #344080;
background-color: transparent;
}
#global {
border-bottom: 1px solid #d0d0d0;
margin-bottom: 2px;
padding: 2px 0 20px 5px;
}
.language-switch {
position: absolute;
left: 83%;
top: 42px;
}
.page-actions {
position: absolute;
right: 25px;
top: 42px;
}

View file

@ -0,0 +1,649 @@
/*
settings specific for view / node objects
*/
/* general */
#content {width: 79%}
#menu {width: 20%;}
#sub-section {width: 0}
h1, h2, h3, h4, h5, h6 {
margin-bottom: 0.4em;
border-bottom: None;
}
a[href]:hover {
text-decoration: none;
color: #803000;
}
pre {
font-size: 100%;
background-color: #f4f4f4;
overflow: scroll;
max-height: 35em;
}
ol, ul, p {
margin-top: 0.4em;
margin-bottom: 0.5em;
}
ol li, ul li {
line-height: 1.5em;
}
blockquote ul {
margin: 0;
}
textarea {
font-size: 100%;
}
table {
border-collapse: collapse;
}
/* class-specific */
.breadcrumbs td {
padding-left: 0;
padding-top: 12px;
}
.description {
font-style: italic;
/* margin-top: 0.5em;*/
margin-bottom: 0.3em;
}
.fields td {
vertical-align: top;
}
.dialog div.heading {
font-weight: bold;
font-size: 140%;
margin: 0.5em 0 0.3em 0;
}
.dialog label {
display: block;
font-weight: bold;
margin-top: 0.5em;
}
.dialog div.buttons {
margin-top: 0.5em;
}
tr.even td {
background-color: transparent;
}
tr.odd td {
background-color: none;
}
table.listing {
margin: 1px;
/*margin-top: 0.5em; */
margin-bottom: 1em;
border: none;
}
table.listing th {
color: #000040;
padding: 0 2px 0 2px;
border: none;
border-bottom: 1px solid lightgrey;
background-color: white;
}
table.listing td {
padding: 2px 2px 2px 2px;
white-space: normal;
vertical-align: middle;
border: none;
border-bottom: 1px dotted #dddddd;
}
fieldset.box table.listing td {
padding: 0 1px 0 1px;
}
table.listing .number {
text-align: right;
}
table.listing .center {
text-align: center;
}
table.listing .nowrap {
white-space: nowrap;
}
table.listing tr.even {
background-color: white;
}
table.listing td.checkbox {
text-align: center;
width: 10px;
padding-left: 2px;
padding-right: 2px;
}
table.listing td.headline {
font-weight: bold;
border: 1px solid lightgrey;
}
table.listing-details td {
white-space: normal;
border: 1px solid lightgrey;
}
table.listing-details tr.heading td {
border: none;
}
table.listing-details tr.heading td h3 {
font-weight: bold;
border: none;
}
table.listing th span.ascending {
background-image: url(/++resource++cybertools.icons/arrowdown.gif);
background-position: right;
background-repeat: no-repeat;
}
table.listing th span.descending {
background-image: url(/++resource++cybertools.icons/arrowup.gif);
background-position: right;
background-repeat: no-repeat;
}
table.records input, table.records textarea {
border: none;
padding: 0;
margin: 0;
width: auto;
}
table.records th {
background-color: #fefefe;
}
table.records th, table.records td {
padding: 0;
margin: 0;
border: 1px solid lightgrey;
}
table.report td {
vertical-align: top;
}
dl.docutils dt {
font-weight: bold;
margin-top: 0.3em;
}
dl.docutils dd {
margin-left: 2em;
}
dl.docutils dd ul li {
margin-left: -1em;
}
fieldset.box {
margin: 1em 0 0.5em 0;
padding: 0.5em;
border: 1px solid #ccc;
}
fieldset.box td {
padding: 0.2em 0.2em 0.2em 0;
}
#body {
margin-left: 5px;
}
.top-actions {
position: absolute;
right: 2em;
top: 1em;
}
.quicksearch {
position: absolute;
right: 2em;
top: 0.8em;
}
.quicksearch input {
font-size: 80%;
}
.language-switch {
position: absolute;
right: 2em;
top: 2.4em;
}
.page-actions {
position: absolute;
right: 2em;
top: 3.8em;
}
.top image {
margin-top: -1px;
}
.content-1 h1, h1 {
font-size: 180%;
font-weight: bold;
color: #444;
padding-top: 0.6em;
}
.content-2 h1, .content-1 h2, h2 {
font-size: 160%;
font-weight: bold;
color: #444;
padding-top: 0.5em;
}
.content-3 h1, .content-2 h2, .content-1 h3, h3 {
font-size: 140%;
font-weight: bold;
color: #444;
padding-top: 0.4em;
}
.content-4 h1, .content-3 h2, .content-2 h3, .content-1 h4, h4 {
font-size: 130%;
font-weight: normal;
padding-top: 0.3em;
}
.content-5 h1, .content-4 h2, .content-3 h3, content-2 h4, h5 {
font-size: 120%;
/* border: none; */
padding-top: 0.2em;
}
.box {
padding: 0;
padding-top: 0;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}
div.box {
margin: 15px 15px 0 15px;
/*border-top: 1px solid #ccc;*/
/*border-bottom: 1px solid #ccc;*/
}
div.box h4 {
font: 110% Verdana, Tahoma, Arial, Helvetica, sans-serif;
color: #000040;
border: none;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
padding: 4px;
padding-top: 1px;
padding-bottom: 3px;
background-color: #eee;
height: auto;
margin-bottom: 0;
}
.box h1, .box h2, .box h3 {
border-bottom: None;
}
.box div.body div.even {
background-color: #f8f8f8;
}
.box div.body div {
padding: 0.2em 0.2em 0.2em 0.3em;
}
div.action {
border-top: 1px solid #eeeeee;
}
div.menu-1, div.menu-2 {
border-top: 1px solid #eeeeee;
font-weight: bold;
}
.box div.body div.menu-3 {
border-top: none;
padding: 0.1em 0 0.2em 1.5em;
}
.box div.body div.menu-4 {
padding-left: 3em;
font-size: 90%
}
.delete-item a[href] {
color: #ff7777;
font-weight: bold;
text-decoration: none;
}
.subcolumn {
display: inline;
float: left;
}
.footer {
text-align: center;
border-top: 1px solid #ccc;
border-bottom: none;
margin-top: 12px;
padding-top: 6px;
}
.object-actions {
float: right;
margin: 0;
}
.object-actions {
padding: 1.5em 0 0 0;
}
.content-2 .object-actions {
padding: 1em 0 0 0;
}
.listing .object-actions {
float: none;
padding: 0;
text-align: center;
}
.icon-action {
display: inline;
}
.flow-left {
float: left;
padding: 0.4em 0.8em 0.8em 0;
}
.flow-right {
float: right;
padding: 0.4em 0.8em 0.8em 0;
}
div.image {
margin-top: 10px;
margin-right: 5px;
}
img.selected {
border: 2px solid #d6dcf6;
}
img.notselected {
border: 2px solid #eff8ff;
}
.navlink {
font-size: 130%;
margin-bottom: 1em;
}
.navlink a {
font-weight: bold;
text-decoration: underline;
}
.subtitle {
font-size: 140%;
font-weight: bold;
margin: 1em 0 0.5em 0;
}
.button {
margin: 1em 0 1em 0;
}
.button a:link, .button a:visited {
padding: 2px 4px 2px 4px;
background-color: #e8e8e8;
text-decoration: None;
color: Black;
border-width: 2px;
border-style: solid;
border-color: #f4f4f4 #989898 #989898 #f4f4f4;
}
.button a:active {
border-color: #989898 #f4f4f4 #f4f4f4 #989898;
}
.itemViews {
border-bottom-width: 2px;
}
.dialog .headline {
font-size: 140%;
font-weight: bold;
padding: 1em 0 1em 0;
}
.error {
background-color: #ffbb00;
padding: 4px;
margin-bottom: 4px;
}
.error-heading {
margin-bottom: 8px;
font-weight: bold;
}
.message {
font-weight: bold;
background-color: #c3d9ff;
padding: 4px;
margin-bottom: 4px;
}
.header-1 {
font-size: 120%;
font-weight: bold;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
/* view modes (tabs) */
ul.view-modes {
padding: 0 0 0 2em;
margin: 0.7em 0 0 0;
white-space: nowrap;
list-style-type: none;
border-bottom: #ccc 1px solid;
background-color: transparent;
}
ul.view-modes li {
display: inline
}
ul.view-modes li a {
padding: 0.15em 1.25em 0.15em 1.25em;
margin: 0 0.5em 0 0;
text-decoration: none;
border: #ccc 1px solid;
background-color: transparent;
}
ul.view-modes li.active a {
border-bottom: #eee 1px solid;
background-color: #eee;
}
ul.view-modes li.inactive a:hover {
background-color: #f8f8f8;
}
/* comments */
div.comment {
padding: 0.5em;
background-color: #eeeeff;
border: 1px solid #aaaaff;
}
.comment h3 {
margin-top: 0;
}
.comment .info {
font-style: italic;
padding-top: 3px;
padding-bottom: 0;
}
/* search stuff */
.searchForm input.button, input.submit {
padding: 2px;
}
/* blog */
.blog .description {
font-size: 90%;
color: #666666;
}
.blogpost .description {
font-size: 90%;
color: #666666;
padding-top: 0.4em;
}
.blog .info, .blogpost .info {
font-style: italic;
font-size: 90%;
color: #666666;
padding-top: 0.4em;
}
/* microart */
.micropart {
background-color: #f7f7f7;
padding: 0 5px 0 5px;
margin: 5px 0 5px 0;
}
.micropart h3,h4,h5 {
font-weight: bold;
margin-bottom: 0.2em;
border-bottom: none;
}
/* calendar, work items */
.today {
color: #444488;
font-weight: bold;
}
.calendar td.arrows {
font-size: 130%;
}
.calendar td.week_number {
color: grey;
}
.calendar td.day {
width: 12%;
}
.calendar td.today {
border: 1px solid red;
font-weight: normal;
}
.calendar .has_events {
font-weight: bold;
background-color: #eeeeff;
}
/* dojo stuff */
.dijitDialog {
background-color: #aaaaaa;
border: 1px solid #999;
padding: 5px;
}
.dijitDialogPaneContent {
background-color: #aaaaaa;
}
.dijitDialog th {
font-size: 120%;
font-weight: bold;
text-align: center;
padding: 0 5px 8px 5px;
}
.dijitDialog td {
padding: 2px;
}
.dijitDialog .headline {
font-weight: bold;
}
.dijitDialog input.text {
width: 100%;
margin-right: 10px;
}
.dijitDialog input.submit {
font-weight: bold;
}
.dijitDialogUnderlay {
background-color: Lightgrey;
}
div.RichTextEditable {
border-top: 2px solid grey;
border-left: 2px solid grey;
border-right: 2px solid #eeeeee;
border-bottom: 2px solid #eeeeee;
}

View file

@ -24,6 +24,7 @@ from cgi import parse_qs
from zope import interface, component
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from zope.traversing.api import getName
from cybertools.typology.interfaces import IType
from loops.browser.lobo import standard
@ -52,8 +53,24 @@ class Base(object):
class SectionView(Base, ConceptView):
pass
@Lazy
def macro(self):
return book_template.macros['section']
@Lazy
def tabview(self):
if self.editable:
return 'index.html'
def getCssClassForResource(self, r):
documentType = self.conceptManager['documenttype']
for c in r.context.getConcepts([self.defaultPredicate]):
if c.conceptType == documentType:
return getName(c)
return 'textelement'
# layout parts - probably obsolete:
class PageLayout(Base, standard.Layout):

View file

@ -4,9 +4,9 @@ type(u'documenttype', u'Dokumentenart', options=u'qualifier:assign',
# book types
type(u'book', u'Buch', viewName=u'', typeInterface=u'',
options=u'action.portlet:create_subtype,edit_concept')
type(u'page', u'Seite', viewName=u'page_layout',
typeInterface=u'loops.compound.book.interfaces.IPage',
options=u'action.portlet:edit_concept')
#type(u'page', u'Seite', viewName=u'page_layout',
# typeInterface=u'loops.compound.book.interfaces.IPage',
# options=u'action.portlet:edit_concept')
type(u'section', u'Kapitel', viewName=u'section_view', typeInterface=u'',
options=u'action.portlet:create_subtype,edit_concept')
@ -20,7 +20,7 @@ concept(u'issubtype', u'is Subtype', u'predicate', options=u'hide_children',
# document types
concept(u'keyquestions', u'Leitfragen', u'documenttype')
concept(u'maintext', u'Haupttext', u'documenttype')
concept(u'textelement', u'Textabschnitt', u'documenttype')
concept(u'quote', u'Zitat', u'documenttype')
concept(u'story', u'Geschichte', u'documenttype')
concept(u'usecase', u'Fallbeispiel', u'documenttype')
@ -28,4 +28,4 @@ concept(u'usecase', u'Fallbeispiel', u'documenttype')
# book structure
child(u'book', u'section', u'issubtype', usePredicate=u'ispartof')
child(u'section', u'section', u'issubtype', usePredicate=u'ispartof')
child(u'section', u'page', u'issubtype', usePredicate=u'ispartof')
#child(u'section', u'page', u'issubtype', usePredicate=u'ispartof')

View file

@ -1,13 +1,44 @@
<html i18n:domain="loops">
<metal:section define-macro="section">
<metal:info use-macro="view/concept_macros/concepttitle" />
<div tal:repeat="related item/resources">
<div class="object-actions" style="padding-top: 0"
tal:define="url python:view.getUrlForTarget(related.context)"
tal:condition="related/editable">
<a i18n:translate="" i18n:attributes="title"
title="Edit"
tal:define="targetUid python:view.getUidForObject(related.context);
url
string:$url/edit_object.html?version=this&targetUid=$targetUid"
tal:attributes="href url;
onclick string:objectDialog('edit', '$url');;
return false">
<img tal:attributes="src
string:$resourceBase/cybertools.icons/vcard_edit.png" /></a>
<a i18n:translate="" i18n:attributes="title"
title="Edit with external editor."
tal:condition="related/xeditable"
tal:attributes="href string:$url/external_edit?version=this">
<img tal:attributes="src
string:$resourceBase/cybertools.icons/application_edit.png" /></a>
</div>
<div tal:attributes="class python:
item.getCssClassForResource(related)"
tal:content="structure related/render" />
</div>
</metal:section>
<!-- layout part macros - obsolete? -->
<metal:part define-macro="headline">
<div tal:define="cell part/getView">
<metal:headline use-macro="item/macros/headline" />
</div>
</metal:part>
<metal:part define-macro="text">
<tal:cell repeat="cell part/getResources">
<div tal:attributes="class cell/cssClass">

View file

@ -219,7 +219,7 @@ class WorkReportInstance(ReportInstance):
def getAllSubtasks(self, concept):
result = []
for c in concept.getChildren():
for c in concept.getChildren([self.view.defaultPredicate]):
if c.conceptType in self.taskTypes:
result.append(c)
result.extend(self.getAllSubtasks(c))
@ -227,7 +227,8 @@ class WorkReportInstance(ReportInstance):
def selectWorkItems(self, task, parts):
# TODO: take states from parts
kw = dict(task=util.getUidForObject(task), state=self.states)
kw = dict(task=util.getUidForObject(baseObject(task)),
state=self.states)
if 'userName' in parts:
kw['userName'] = parts['userName'].comparisonValue
wi = self.workItems