Merge branch 'master' into zmi-restrictions

This commit is contained in:
Helmut Merz 2011-10-20 09:59:02 +02:00
commit cfc87f13ba
14 changed files with 260 additions and 75 deletions

View file

@ -6,6 +6,9 @@ $Id$
1.1 1.1
--- ---
- Lobo layout: provide new part: image grid; make sure image is not repeated if
it already appears in header part
- new special view 'listsubobjects' for nodes
- allow for adoption of relations to a predicate interface; - allow for adoption of relations to a predicate interface;
with example implementation for a 'has Role' predicate in loops.organize with example implementation for a 'has Role' predicate in loops.organize
- external collection: provide functionality for automatically populate - external collection: provide functionality for automatically populate

View file

@ -350,7 +350,12 @@ class ConceptView(BaseView):
#IOptions(adapted(pr.predicate))('hide_parents_for', [])): #IOptions(adapted(pr.predicate))('hide_parents_for', [])):
IOptions(pr.predicate)('hide_parents_for', [])): IOptions(pr.predicate)('hide_parents_for', [])):
return True return True
hideRoles = IOptions(adapted(pr.first.conceptType))('hide_for', None) hideRoles = None
options = component.queryAdapter(adapted(pr.first), IOptions)
if options is not None:
hideRoles = options('hide_for', None)
if not hideRoles:
hideRoles = IOptions(adapted(pr.first.conceptType))('hide_for', None)
if hideRoles is not None: if hideRoles is not None:
principal = self.request.principal principal = self.request.principal
if (IUnauthenticatedPrincipal.providedBy(principal) and if (IUnauthenticatedPrincipal.providedBy(principal) and
@ -395,10 +400,28 @@ class ConceptView(BaseView):
fv = FilterView(self.context, self.request) fv = FilterView(self.context, self.request)
rels = self.context.getResourceRelations() rels = self.context.getResourceRelations()
for r in rels: for r in rels:
#yield self.childViewFactory(r, self.request, contextIsSecond=True)
if fv.check(r.first): if fv.check(r.first):
yield ResourceRelationView(r, self.request, contextIsSecond=True) yield ResourceRelationView(r, self.request, contextIsSecond=True)
@Lazy
def resourcesList(self):
from loops.browser.resource import ResourceRelationView
return [ResourceRelationView(r, self.request, contextIsSecond=True)
for r in self.context.getResourceRelations()]
@Lazy
def resourcesByType(self):
result = dict(texts=[], images=[], files=[])
for rv in self.resourcesList:
r = rv.context
if r.contentType.startswith('text/'):
result['texts'].append(r)
if r.contentType.startswith('image/'):
result['images'].append(r)
else:
result['files'].append(r)
return result
def unique(self, rels): def unique(self, rels):
result = Jeep() result = Jeep()
for r in rels: for r in rels:

View file

@ -509,6 +509,14 @@
factory="loops.browser.node.ListResources" factory="loops.browser.node.ListResources"
permission="zope.View" /> permission="zope.View" />
<zope:adapter
name="listsubobjects"
for="loops.interfaces.INode
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.browser.node.ListSubobjects"
permission="zope.View" />
<zope:adapter <zope:adapter
name="listchildren" name="listchildren"
for="loops.interfaces.INode for="loops.interfaces.INode
@ -562,6 +570,12 @@
class="loops.browser.node.ObjectInfo" class="loops.browser.node.ObjectInfo"
permission="zope.View" /> permission="zope.View" />
<page
name="meta_info.html"
for="loops.interfaces.INode"
class="loops.browser.node.MetaInfo"
permission="zope.View" />
<page <page
name="create_object.html" name="create_object.html"
for="loops.interfaces.INode" for="loops.interfaces.INode"

View file

@ -38,7 +38,29 @@
</tr> </tr>
<tr tal:repeat="info item/additionalInfos"> <tr tal:repeat="info item/additionalInfos">
<td><span i18n:translate="" <td><span i18n:translate=""
tal:content="info/label">Creators</span>:</td> tal:content="info/label">Meta</span>:</td>
<td tal:content="structure info/value"></td>
</tr>
<tr>
<td colspan="2"><br />
<input type="button" value="Close" onclick="closeDialog()"
i18n:attributes="value" />
</td>
</tr>
</table>
</metal:info>
<metal:info define-macro="meta_info"
tal:define="item nocall:view/item">
<table class="object_info" width="400">
<tr>
<td colspan="2">
<h2 tal:content="item/title">Information</h2></td>
</tr>
<tr tal:repeat="info item/additionalInfos">
<td><span i18n:translate=""
tal:content="info/label">Meta</span>:</td>
<td tal:content="structure info/value"></td> <td tal:content="structure info/value"></td>
</tr> </tr>
<tr> <tr>
@ -48,5 +70,4 @@
</td> </td>
</tr> </tr>
</table> </table>
</metal:info> </metal:info>

View file

@ -39,6 +39,14 @@
factory="loops.browser.lobo.standard.List2" factory="loops.browser.lobo.standard.List2"
permission="zope.View" /> permission="zope.View" />
<zope:adapter
name="lobo_h0"
for="loops.interfaces.IConcept
loops.browser.skin.Lobo"
provides="zope.interface.Interface"
factory="loops.browser.lobo.standard.Header0"
permission="zope.View" />
<zope:adapter <zope:adapter
name="lobo_h1" name="lobo_h1"
for="loops.interfaces.IConcept for="loops.interfaces.IConcept
@ -66,11 +74,11 @@
<!-- parts for displaying resources --> <!-- parts for displaying resources -->
<zope:adapter <zope:adapter
name="lobo_rg3" name="lobo_ig3"
for="loops.interfaces.IConcept for="loops.interfaces.IConcept
loops.browser.skin.Lobo" loops.browser.skin.Lobo"
provides="zope.interface.Interface" provides="zope.interface.Interface"
factory="loops.browser.lobo.standard.ResourceGrid3" factory="loops.browser.lobo.standard.ImageGrid3"
permission="zope.View" /> permission="zope.View" />
</configure> </configure>

View file

@ -12,9 +12,9 @@
<tal:cell repeat="cell part/getChildren"> <tal:cell repeat="cell part/getChildren">
<div tal:attributes="class cell/cssClass; <div tal:attributes="class cell/cssClass;
style cell/style"> style cell/style">
<metal:image use-macro="item/macros/image" />
<a tal:attributes="href cell/targetUrl; <a tal:attributes="href cell/targetUrl;
title cell/description"> title cell/description">
<metal:image use-macro="item/macros/image" />
<div class="legend"> <div class="legend">
<b tal:content="cell/title" /><br /> <b tal:content="cell/title" /><br />
<i tal:content="cell/description" /> <i tal:content="cell/description" />
@ -29,10 +29,8 @@
<tal:cell repeat="cell part/getChildren"> <tal:cell repeat="cell part/getChildren">
<div tal:condition="cell/img" <div tal:condition="cell/img"
tal:attributes="class python:cell.cssClass[0]"> tal:attributes="class python:cell.cssClass[0]">
<a tal:attributes="href cell/targetUrl; <metal:image use-macro="item/macros/image" />
title cell/description"> <br />&nbsp;
<metal:image use-macro="item/macros/image" />
</a><br />&nbsp;
</div> </div>
<div tal:attributes="class python:cell.cssClass[1]"> <div tal:attributes="class python:cell.cssClass[1]">
<a tal:attributes="href cell/targetUrl"> <a tal:attributes="href cell/targetUrl">
@ -48,14 +46,24 @@
<metal:block define-macro="header"> <metal:block define-macro="header">
<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 tal:define="showImageLink python:True" <tal:image condition="part/showImage">
tal:attributes="class python:part.cssClass[0]"> <div tal:define="showImageLink python:True"
<metal:image use-macro="item/macros/image" /> tal:attributes="class python:part.cssClass[0]">
</div> <metal:image use-macro="item/macros/image" />
<span tal:condition="cell/img/showInfo|nothing">
<a tal:define="url string:${cell/img/url}/meta_info.html"
tal:attributes="href url;
onclick string:objectDialog('', '$url');;
return false">
<img tal:attributes="src
string:${controller/resourceBase}/cybertools.icons/info.png" />
</a></span>
</div>
</tal:image>
<div tal:attributes="class python:part.cssClass[1]"> <div tal:attributes="class python:part.cssClass[1]">
<span tal:content="structure cell/renderedTextDescription" /> <span tal:content="structure cell/renderedTextDescription" />
</div> </div>
<tal:break condition="cell/img"> <tal:break condition="python:part.showImage and cell.img">
<br style="clear: both" />&nbsp;</tal:break> <br style="clear: both" />&nbsp;</tal:break>
<div tal:condition="cell/renderedText" <div tal:condition="cell/renderedText"
tal:attributes="class python:part.cssClass[2]"> tal:attributes="class python:part.cssClass[2]">
@ -67,18 +75,25 @@
<!-- resources listing macros --> <!-- resources listing macros -->
<metal:block define-macro="rgrid"> <metal:block define-macro="imagegrid"
<tal:cell repeat="cell part/getResources"> tal:define="showImageLink python:True">
<tal:cell repeat="cell part/getImages">
<div tal:attributes="class cell/cssClass; <div tal:attributes="class cell/cssClass;
style cell/style"> style cell/style">
<a tal:attributes="href cell/targetUrl;
title cell/description">
<metal:image use-macro="item/macros/image" /> <metal:image use-macro="item/macros/image" />
<div class="legend"> <div class="legend">
<b tal:content="cell/title" /><br /> <b tal:content="cell/title" />
<span tal:condition="cell/img/showInfo|nothing">
<a tal:define="url string:${cell/img/url}/meta_info.html"
tal:attributes="href url;
onclick string:objectDialog('', '$url');;
return false">
<img tal:attributes="src
string:${controller/resourceBase}/cybertools.icons/info.png" />
</a></span>
<br />
<i tal:content="cell/description" /> <i tal:content="cell/description" />
</div> </div>
</a>
</div> </div>
</tal:cell> </tal:cell>
</metal:block> </metal:block>
@ -89,14 +104,21 @@
<metal:image define-macro="image"> <metal:image define-macro="image">
<tal:img condition="cell/img"> <tal:img condition="cell/img">
<a title="Information about this object." <a title="Information about this object."
tal:omit-tag="not:showImageLink|python:False" dojoType="dojox.image.Lightbox" group="mediasset"
i18n:attributes="title" i18n:attributes="title"
tal:define="url string:${cell/img/url}/object_info.html" tal:attributes="href cell/img/fullImageUrl;
tal:attributes="href url; title cell/img/title">
onclick string:objectDialog('', '$url?dialog=');; return false"> <img tal:condition="showImageLink|python:False"
<img tal:condition="cell/img"
tal:attributes="src cell/img/src; tal:attributes="src cell/img/src;
class cell/img/cssClass" /> class cell/img/cssClass;
alt cell/title" />
</a>
<a tal:condition="not:showImageLink|python:False"
tal:attributes="href cell/targetUrl;
title cell/title">
<img tal:attributes="src cell/img/src;
class cell/img/cssClass;
alt cell/title" />
</a> </a>
</tal:img> </tal:img>
</metal:image> </metal:image>

View file

@ -31,7 +31,6 @@ from cybertools.typology.interfaces import IType
from loops.browser.concept import ConceptView as BaseConceptView from loops.browser.concept import ConceptView as BaseConceptView
from loops.browser.concept import ConceptRelationView as BaseConceptRelationView from loops.browser.concept import ConceptRelationView as BaseConceptRelationView
from loops.browser.resource import ResourceView as BaseResourceView from loops.browser.resource import ResourceView as BaseResourceView
from loops.browser.resource import ResourceRelationView as BaseResourceRelationView
from loops.common import adapted, baseObject from loops.common import adapted, baseObject
@ -64,7 +63,6 @@ class ConceptView(BaseConceptView):
def __init__(self, context, request): def __init__(self, context, request):
super(ConceptView, self).__init__(baseObject(context), request) super(ConceptView, self).__init__(baseObject(context), request)
self.adapted = context
@Lazy @Lazy
def resources(self): def resources(self):
@ -78,6 +76,11 @@ class ConceptView(BaseConceptView):
result['files'].append(r) result['files'].append(r)
return result return result
@Lazy
def images(self):
for r in self.resources['images']:
yield r
# properties from base class: title, description, renderedDescription # properties from base class: title, description, renderedDescription
@Lazy @Lazy
@ -113,23 +116,19 @@ class ConceptView(BaseConceptView):
@Lazy @Lazy
def img(self): def img(self):
self.registerDojoLightbox() # also provides access to info popup self.registerDojoLightbox() # also provides access to info popup
for r in self.resources['images']: for r in self.parentView.parent.images:
url = self.nodeView.getUrlForTarget(r) # fetch from iterator on layout object: avoid duplicates
src = ('%s/mediaasset.html?v=%s' % (url, self.parentView.imageSize)) url = self.nodeView.getUrlForTarget(r)
return dict(src=src, url=url, src = ('%s/mediaasset.html?v=%s' % (url, self.parentView.imageSize))
cssClass=self.parentView.imageCssClass) fullSrc = ('%s/mediaasset.html?v=%s' % (url, self.parentView.fullImageSize))
adImg = adapted(r)
showInfo = adImg.showInfo and adImg.metaInfo
return dict(src=src, fullImageUrl=fullSrc, title=r.title,
url=url, cssClass=self.parentView.imageCssClass,
showInfo=showInfo)
class ConceptRelationView(BaseConceptRelationView, ConceptView): class Layout(Base, ConceptView):
def __init__(self, relation, request, contextIsSecond=False,
parent=None, idx=0):
BaseConceptRelationView.__init__(self, relation, request, contextIsSecond)
self.parentView = parent
self.idx = idx
class Layout(Base):
macroName = 'layout' macroName = 'layout'
@ -140,11 +139,13 @@ class Layout(Base):
parts = (self.options('parts') or parts = (self.options('parts') or
self.typeOptions('parts') or self.typeOptions('parts') or
['h1', 'g3']) ['h1', 'g3'])
ti = adapted(self.context.conceptType).typeInterface
for p in parts: for p in parts:
viewName = 'lobo_' + p viewName = 'lobo_' + p
view = component.queryMultiAdapter((self.context, self.request), view = component.queryMultiAdapter((self.context, self.request),
name=viewName) name=viewName)
if view is not None: if view is not None:
view.parent = self
result.append(view) result.append(view)
return result return result
@ -152,9 +153,11 @@ class Layout(Base):
class BasePart(Base): class BasePart(Base):
imageSize = 'small' imageSize = 'small'
fullImageSize = 'medium'
imageCssClass = '' imageCssClass = ''
height = 260 height = 260
gridPattern = [] gridPattern = []
showImage = True
def getChildren(self): def getChildren(self):
subtypeNames = (self.params.get('subtypes') or [''])[0].split(',') subtypeNames = (self.params.get('subtypes') or [''])[0].split(',')
@ -175,6 +178,12 @@ class BasePart(Base):
view.parentView = self view.parentView = self
return view return view
def getImages(self):
result = []
for idx, img in enumerate(self.parent.images):
result.append(ResourceView(img, self.request, parent=self, idx=idx))
return result
class Grid3(BasePart): class Grid3(BasePart):
@ -198,6 +207,14 @@ class List2(BasePart):
gridPattern = [['span-4 clear', 'span-2 last']] gridPattern = [['span-4 clear', 'span-2 last']]
class Header0(BasePart):
macroName = 'header'
cssClass = ['span-6 last', 'clear']
showImage = False
cssClass = ['', 'span-6 last', 'clear']
class Header1(BasePart): class Header1(BasePart):
macroName = 'header' macroName = 'header'
@ -212,13 +229,46 @@ class Header2(BasePart):
cssClass = ['span-4', 'span-2 last', 'clear'] cssClass = ['span-4', 'span-2 last', 'clear']
# layout components for presenting lists of resources # resource parts
class ResourceRelationView(BaseResourceRelationView):
class ImageGrid3(BasePart):
macroName = 'imagegrid'
imageSize = 'small'
height = 'auto; padding-bottom: 10px'
gridPattern = ['span-2', 'span-2', 'span-2 last']
# relation views, used for cells (components) of lists and grids
class ConceptRelationView(BaseConceptRelationView, ConceptView):
def __init__(self, relation, request, contextIsSecond=False, def __init__(self, relation, request, contextIsSecond=False,
parent=None, idx=0): parent=None, idx=0):
BaseResourceRelationView.__init__(self, relation, request, contextIsSecond) BaseConceptRelationView.__init__(self, relation, request, contextIsSecond)
self.parentView = parent
self.idx = idx
@Lazy
def img(self):
self.registerDojoLightbox() # also provides access to info popup
for r in self.images:
# fetch from iterator on layout object: avoid duplicates
url = self.nodeView.getUrlForTarget(r)
src = ('%s/mediaasset.html?v=%s' % (url, self.parentView.imageSize))
fullSrc = ('%s/mediaasset.html?v=%s' % (url, self.parentView.fullImageSize))
adImg = adapted(r)
showInfo = adImg.showInfo and adImg.metaInfo
return dict(src=src, fullImageUrl=fullSrc, title=r.title,
url=url, cssClass=self.parentView.imageCssClass,
showInfo=showInfo)
class ResourceView(BaseResourceView):
def __init__(self, resource, request, parent=None, idx=0):
BaseResourceView.__init__(self, resource, request)
self.parentView = parent self.parentView = parent
self.idx = idx self.idx = idx
@ -241,25 +291,10 @@ class ResourceRelationView(BaseResourceRelationView):
self.registerDojoLightbox() # also provides access to info popup self.registerDojoLightbox() # also provides access to info popup
url = self.nodeView.getUrlForTarget(self.context) url = self.nodeView.getUrlForTarget(self.context)
src = ('%s/mediaasset.html?v=%s' % (url, self.parentView.imageSize)) src = ('%s/mediaasset.html?v=%s' % (url, self.parentView.imageSize))
return dict(src=src, url=url, fullSrc = ('%s/mediaasset.html?v=%s' % (url, self.parentView.fullImageSize))
cssClass=self.parentView.imageCssClass) adImg = adapted(self.context)
showInfo = adImg.showInfo and adImg.metaInfo
class ResourcesPart(BasePart): return dict(src=src, fullImageUrl=fullSrc, title=self.context.title,
url=url, cssClass=self.parentView.imageCssClass,
def getResources(self): showInfo=showInfo)
result = []
resourceRels = self.context.getResourceRelations()
for idx, r in enumerate(resourceRels):
result.append(ResourceRelationView(r, self.request,
contextIsSecond=True, parent=self, idx=idx))
return result
class ResourceGrid3(ResourcesPart):
macroName = 'rgrid'
imageSize = 'small'
height = 'auto; padding-bottom: 10px'
gridPattern = ['span-2', 'span-2', 'span-2 last']

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2010 Helmut Merz helmutm@cy55.de # Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -607,6 +607,15 @@ class ObjectInfo(NodeView):
return self.request.get('dialog', 'object_info') return self.request.get('dialog', 'object_info')
class MetaInfo(ObjectInfo):
__call__ = innerHtml
@Lazy
def macro(self):
return self.macros['meta_info']
class InlineEdit(NodeView): class InlineEdit(NodeView):
""" Provides inline editor as inner HTML""" """ Provides inline editor as inner HTML"""
@ -676,6 +685,11 @@ class ListChildren(SpecialNodeView):
macroName = 'listchildren' macroName = 'listchildren'
class ListSubobjects(SpecialNodeView):
macroName = 'listsubobjects'
class ConfigureView(NodeView): class ConfigureView(NodeView):
""" An editing view for configuring a node, optionally creating """ An editing view for configuring a node, optionally creating
a target object. a target object.

View file

@ -166,12 +166,47 @@
<a href="#" <a href="#"
tal:attributes="href string:${view/url}/.${related/uniqueId}; tal:attributes="href string:${view/url}/.${related/uniqueId};
title related/description" title related/description"
tal:content="related/title">Resource Title</a> tal:content="related/title">Concept Title</a>
</div> </div>
</div> </div>
</metal:children> </metal:children>
<metal:subobjects define-macro="listsubobjects"
tal:define="target nocall:item/targetObjectView">
<div class="content-1"
tal:content="structure item/body"
tal:attributes="ondblclick python:
target and target.openEditWindow('configure.html')
or item.openEditWindow();
id string:${view/itemNum}.body;">
Listing
</div>
<div tal:condition="nocall:target">
<div tal:attributes="ondblclick python: target.openEditWindow('configure.html')"
tal:define="children python:list(target.children())"
tal:condition="children">
<h3 i18n:translate="">Children</h3>
<div tal:repeat="related children">
<a tal:attributes="href python:view.getUrlForTarget(related);
title related/description"
tal:content="related/title">Concept Title</a>
</div>
</div>
<div tal:attributes="ondblclick python: target.openEditWindow('resources.html')"
tal:define="resources python:list(target.resources())"
tal:condition="resources">
<h3 i18n:translate="">Resources</h3>
<div tal:repeat="related resources">
<a tal:attributes="href python:view.getUrlForTarget(related);
title related/description"
tal:content="related/title">Resource Title</a>
</div>
</div>
</div>
</metal:subobjects>
<!-- menu --> <!-- menu -->
<metal:menu define-macro="menu" <metal:menu define-macro="menu"

View file

@ -243,8 +243,10 @@ class ResourceView(BaseView):
# actions # actions
def getPortletActions(self, page=None, target=None): def getPortletActions(self, page=None, target=None):
return actions.get('portlet', ['edit_object'], view=self, page=page, if canWrite(target.context, 'data'):
target=target) return actions.get('portlet', ['edit_object'], 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']

View file

@ -443,7 +443,7 @@ img.notselected {
/* lobo layout-specific classes */ /* lobo layout-specific classes */
.legend { .legend {
margin-top: 3px; margin-top: 1px;
} }
/* comments */ /* comments */

View file

@ -296,6 +296,7 @@ class IBaseResource(ILoopsObject):
metaInfo = Attribute('Optional additional information about the resource ' metaInfo = Attribute('Optional additional information about the resource '
'provided as text.') 'provided as text.')
showInfo = Attribute('Show object information in the standard user interface.')
def getType(): def getType():
""" Return a concept that provides the object's type, i.e. the """ Return a concept that provides the object's type, i.e. the

View file

@ -1,6 +1,7 @@
<metal:block define-macro="asset"> <metal:block define-macro="asset">
<div tal:attributes="ondblclick python: item.openEditWindow('edit.html')"> <div tal:attributes="ondblclick python: item.openEditWindow('edit.html')">
<div metal:use-macro="views/node_macros/object_actions" /> <tal:actions condition="view/showObjectActions">
<div metal:use-macro="views/node_macros/object_actions" /></tal:actions>
<h1 tal:content="item/title">Title</h1><br /> <h1 tal:content="item/title">Title</h1><br />
<p tal:define="url python: view.getUrlForTarget(item)"> <p tal:define="url python: view.getUrlForTarget(item)">
<a tal:omit-tag="view/isAnonymous" <a tal:omit-tag="view/isAnonymous"

View file

@ -39,3 +39,9 @@ class IMediaAsset(IMediaAsset, IExternalFile):
missing_value=u'', missing_value=u'',
required=False) required=False)
showInfo = schema.Bool(
title=_(u'Show Object Information'),
description=_(u'Show object information in the standard user interface.'),
default=False,
required=False)