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): class BaseView(GenericView, I18NView):
actions = {} actions = {}
portlet_actions = []
icon = None icon = None
modeName = 'view' modeName = 'view'
isToplevel = False isToplevel = False

View file

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

View file

@ -27,10 +27,19 @@
<tal:actions condition="view/showObjectActions"> <tal:actions condition="view/showObjectActions">
<div metal:use-macro="views/node_macros/object_actions" /> <div metal:use-macro="views/node_macros/object_actions" />
</tal: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" <a tal:omit-tag="python: level > 1"
tal:attributes="href request/URL" tal:attributes="href request/URL"
tal:content="item/title">Title</a> 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> </h1>
</metal:title> </metal:title>
<p tal:define="description description|item/renderedDescription" <p tal:define="description description|item/renderedDescription"

View file

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

View file

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

View file

@ -240,6 +240,27 @@
</metal:actions> </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"> <metal:actions define-macro="view_modes">
<ul class="view-modes" <ul class="view-modes"
tal:define="viewModes view/viewModes" tal:define="viewModes view/viewModes"

View file

@ -227,6 +227,15 @@ class ResourceView(BaseView):
response.setHeader('Last-Modified', modified.strftime(format)) response.setHeader('Last-Modified', modified.strftime(format))
return data 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): def renderText(self, text, contentType):
if contentType == 'text/restructured' and wikiLinksActive(self.loopsRoot): if contentType == 'text/restructured' and wikiLinksActive(self.loopsRoot):
# TODO: make this more flexible/configurable # TODO: make this more flexible/configurable
@ -400,15 +409,6 @@ class DocumentView(ResourceView):
@Lazy @Lazy
def view(self): return self 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 @Lazy
def inlineEditable(self): def inlineEditable(self):
return (self.inlineEditingActive return (self.inlineEditingActive

View file

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

View file

@ -6,6 +6,10 @@ from cybertools.browser.liquid import Liquid
from cybertools.browser.blue import Blue 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): class Loopz(Liquid):
""" The Loopz (neutral enduser) skin """ """ The Loopz (neutral enduser) skin """

View file

@ -5,6 +5,28 @@
xmlns="http://namespaces.zope.org/browser" xmlns="http://namespaces.zope.org/browser"
i18n_domain="loops"> 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 --> <!-- Loopz skin -->
<zope:interface <zope:interface

View file

@ -27,23 +27,7 @@
<div id="content" class="span-6" <div id="content" class="span-6"
metal:define-macro="content"> metal:define-macro="content">
<metal:breadcrumbs define-slot="breadcrumbs"> <metal:breadcrumbs define-slot="breadcrumbs">
<table class="breadcrumbs" <metal:tabs use-macro="views/node_macros/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:breadcrumbs>
<div metal:define-slot="actions"></div> <div metal:define-slot="actions"></div>
<div metal:define-slot="message"></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 import interface, component
from zope.app.pagetemplate import ViewPageTemplateFile from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.traversing.api import getName
from cybertools.typology.interfaces import IType from cybertools.typology.interfaces import IType
from loops.browser.lobo import standard from loops.browser.lobo import standard
@ -52,8 +53,24 @@ class Base(object):
class SectionView(Base, ConceptView): 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): class PageLayout(Base, standard.Layout):

View file

@ -4,9 +4,9 @@ type(u'documenttype', u'Dokumentenart', options=u'qualifier:assign',
# book types # book types
type(u'book', u'Buch', viewName=u'', typeInterface=u'', type(u'book', u'Buch', viewName=u'', typeInterface=u'',
options=u'action.portlet:create_subtype,edit_concept') options=u'action.portlet:create_subtype,edit_concept')
type(u'page', u'Seite', viewName=u'page_layout', #type(u'page', u'Seite', viewName=u'page_layout',
typeInterface=u'loops.compound.book.interfaces.IPage', # typeInterface=u'loops.compound.book.interfaces.IPage',
options=u'action.portlet:edit_concept') # options=u'action.portlet:edit_concept')
type(u'section', u'Kapitel', viewName=u'section_view', typeInterface=u'', type(u'section', u'Kapitel', viewName=u'section_view', typeInterface=u'',
options=u'action.portlet:create_subtype,edit_concept') 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 # document types
concept(u'keyquestions', u'Leitfragen', u'documenttype') 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'quote', u'Zitat', u'documenttype')
concept(u'story', u'Geschichte', u'documenttype') concept(u'story', u'Geschichte', u'documenttype')
concept(u'usecase', u'Fallbeispiel', u'documenttype') concept(u'usecase', u'Fallbeispiel', u'documenttype')
@ -28,4 +28,4 @@ concept(u'usecase', u'Fallbeispiel', u'documenttype')
# book structure # book structure
child(u'book', u'section', u'issubtype', usePredicate=u'ispartof') child(u'book', u'section', u'issubtype', usePredicate=u'ispartof')
child(u'section', 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"> <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"> <metal:part define-macro="headline">
<div tal:define="cell part/getView"> <div tal:define="cell part/getView">
<metal:headline use-macro="item/macros/headline" /> <metal:headline use-macro="item/macros/headline" />
</div> </div>
</metal:part> </metal:part>
<metal:part define-macro="text"> <metal:part define-macro="text">
<tal:cell repeat="cell part/getResources"> <tal:cell repeat="cell part/getResources">
<div tal:attributes="class cell/cssClass"> <div tal:attributes="class cell/cssClass">

View file

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