improvements for external collection and media asset: integration now working correctly, with generation of scal variants for media assets
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3105 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
60c7d22e61
commit
be71f62a6e
9 changed files with 104 additions and 35 deletions
|
@ -108,6 +108,7 @@ class EditForm(form.EditForm):
|
|||
class BaseView(GenericView, I18NView):
|
||||
|
||||
actions = {}
|
||||
icon = None
|
||||
|
||||
def __init__(self, context, request):
|
||||
super(BaseView, self).__init__(context, request)
|
||||
|
@ -127,6 +128,8 @@ class BaseView(GenericView, I18NView):
|
|||
def conceptMacros(self):
|
||||
return concept_macros.macros
|
||||
|
||||
concept_macros = conceptMacros
|
||||
|
||||
@Lazy
|
||||
def name(self):
|
||||
return getName(self.context)
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
|
||||
<metal:data define-macro="conceptdata">
|
||||
<div tal:attributes="class string:content-$level;">
|
||||
<metal:fields use-macro="item/template/macros/concepttitle" />
|
||||
<metal:fields use-macro="item/template/macros/conceptfields" />
|
||||
<metal:fields use-macro="item/template/macros/conceptchildren" />
|
||||
<metal:fields use-macro="item/template/macros/conceptresources" />
|
||||
<metal:fields use-macro="view/work_macros/workitems" />
|
||||
<metal:fields use-macro="view/comment_macros/comments" />
|
||||
<metal:block use-macro="view/concept_macros/concepttitle" />
|
||||
<metal:slot define-slot="fields">
|
||||
<metal:block use-macro="view/concept_macros/conceptfields" />
|
||||
</metal:slot>
|
||||
<metal:block use-macro="view/concept_macros/conceptchildren" />
|
||||
<metal:block use-macro="view/concept_macros/conceptresources" />
|
||||
<metal:block use-macro="view/work_macros/workitems" />
|
||||
<metal:block use-macro="view/comment_macros/comments" />
|
||||
</div>
|
||||
</metal:data>
|
||||
|
||||
|
@ -154,7 +156,10 @@
|
|||
<a href="#"
|
||||
tal:attributes="href string:${view/url}/.target${related/uniqueId};
|
||||
title description">
|
||||
<span tal:replace="related/title">Resource Title</span>
|
||||
<img tal:define="icon related/icon"
|
||||
tal:condition="icon"
|
||||
tal:attributes="src icon/src" />
|
||||
<div tal:content="related/title">Resource Title</div>
|
||||
</a>
|
||||
</td>
|
||||
<td><span tal:replace="related/longTypeTitle">Type</span></td>
|
||||
|
|
|
@ -48,7 +48,9 @@ from loops.browser.concept import ConceptRelationView, ConceptConfigureView
|
|||
from loops.browser.node import NodeView, node_macros
|
||||
from loops.common import adapted, NameChooser
|
||||
from loops.interfaces import IBaseResource, IDocument, IMediaAsset, ITextDocument
|
||||
from loops.interfaces import IMediaAsset as legacy_IMediaAsset
|
||||
from loops.interfaces import ITypeConcept
|
||||
from loops.media.interfaces import IMediaAsset
|
||||
from loops.organize.stateful.browser import statefulActions
|
||||
from loops.versioning.browser import version_macros
|
||||
from loops.versioning.interfaces import IVersionable
|
||||
|
@ -95,13 +97,19 @@ class DocumentEditForm(EditForm):
|
|||
|
||||
|
||||
class MediaAssetEditForm(EditForm):
|
||||
form_fields = FormFields(IMediaAsset)
|
||||
form_fields = FormFields(legacy_IMediaAsset)
|
||||
|
||||
|
||||
class ResourceView(BaseView):
|
||||
|
||||
template = ViewPageTemplateFile('resource_macros.pt')
|
||||
|
||||
@Lazy
|
||||
def icon(self):
|
||||
if IMediaAsset.providedBy(self.adapted):
|
||||
return dict(src='%s/mediaasset.html?v=minithumb' %
|
||||
(self.nodeView.getUrlForTarget(self.context)))
|
||||
|
||||
@property
|
||||
def macro(self):
|
||||
if 'image/' in self.context.contentType:
|
||||
|
|
|
@ -59,9 +59,15 @@ class ExternalCollectionAdapter(AdapterBase):
|
|||
implements(IExternalCollection)
|
||||
adapts(IConcept)
|
||||
|
||||
_adapterAttributes = ('context', '__parent__',)
|
||||
_adapterAttributes = ('context', '__parent__', 'exclude')
|
||||
_contextAttributes = list(IExternalCollection) + list(IConcept)
|
||||
|
||||
def getExclude(self):
|
||||
return getattr(self.context, '_exclude', None) or []
|
||||
def setExclude(self, value):
|
||||
self.context._exclude = value
|
||||
exclude = property(getExclude, setExclude)
|
||||
|
||||
def update(self):
|
||||
existing = self.context.getResources()
|
||||
#old = dict((adapted(obj).uniqueAddress, obj) for obj in existing)
|
||||
|
@ -109,26 +115,43 @@ class DirectoryCollectionProvider(object):
|
|||
|
||||
implements(IExternalCollectionProvider)
|
||||
|
||||
extFileTypeMapping = {
|
||||
'image/*': 'media_asset',
|
||||
'*/*': 'extfile',
|
||||
}
|
||||
|
||||
def collect(self, client):
|
||||
directory = self.getDirectory(client)
|
||||
pattern = re.compile(client.pattern or '.*')
|
||||
for path, dirs, files in os.walk(directory):
|
||||
if '.svn' in dirs:
|
||||
del dirs[dirs.index('.svn')]
|
||||
for ex in client.exclude:
|
||||
if ex in dirs:
|
||||
del dirs[dirs.index(ex)]
|
||||
for f in files:
|
||||
if pattern.match(f):
|
||||
mtime = os.stat(os.path.join(path, f))[stat.ST_MTIME]
|
||||
yield (os.path.join(path[len(directory)+1:], f),
|
||||
datetime.fromtimestamp(mtime))
|
||||
|
||||
def createExtFileObjects(self, client, addresses, extFileType=None):
|
||||
if extFileType is None:
|
||||
extFileType = client.context.getLoopsRoot().getConceptManager()['extfile']
|
||||
def createExtFileObjects(self, client, addresses, extFileTypes=None):
|
||||
if extFileTypes is None:
|
||||
cm = client.context.getLoopsRoot().getConceptManager()
|
||||
extFileTypes = dict((k, cm.get(v))
|
||||
for k, v in self.extFileTypeMapping.items())
|
||||
container = client.context.getLoopsRoot().getResourceManager()
|
||||
directory = self.getDirectory(client)
|
||||
for addr in addresses:
|
||||
name = self.generateName(container, addr)
|
||||
title = self.generateTitle(addr)
|
||||
contentType = guess_content_type(addr,
|
||||
default='application/octet-stream')[0]
|
||||
extFileType = extFileTypes.get(contentType)
|
||||
if extFileType is None:
|
||||
extFileType = extFileTypes.get(contentType.split('/')[0] + '/*')
|
||||
if extFileType is None:
|
||||
extFileType = extFileTypes['*/*']
|
||||
obj = addAndConfigureObject(
|
||||
container, Resource, name,
|
||||
title=title,
|
||||
|
@ -136,9 +159,8 @@ class DirectoryCollectionProvider(object):
|
|||
externalAddress=addr,
|
||||
storageName='fullpath',
|
||||
storageParams=dict(subdirectory=directory),
|
||||
contentType = guess_content_type(addr,
|
||||
default='application/octet-stream')[0]
|
||||
)
|
||||
contentType=contentType,
|
||||
)
|
||||
yield obj
|
||||
|
||||
def getDirectory(self, client):
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
<metal:resources define-macro="render_collection"
|
||||
tal:define="dummy item/update">
|
||||
<html i18n:domain="loops">
|
||||
|
||||
<metal:concept use-macro="item/template/macros/conceptdata" />
|
||||
|
||||
<form action="." method="post">
|
||||
<input type="submit" name="update" value="Update Collection" />
|
||||
</form>
|
||||
<metal:block define-macro="render_collection"
|
||||
tal:define="dummy item/update">
|
||||
|
||||
</metal:resources>
|
||||
<metal:block use-macro="view/concept_macros/conceptdata">
|
||||
<metal:fill fill-slot="fields">
|
||||
<metal:block use-macro="view/concept_macros/conceptfields" />
|
||||
<form action="." method="post">
|
||||
<input type="submit" name="update" value="Update Collection" />
|
||||
</form>
|
||||
</metal:fill>
|
||||
</metal:block>
|
||||
|
||||
</metal:block>
|
||||
|
||||
|
||||
</html>
|
|
@ -50,13 +50,13 @@ class IExternalCollection(IConceptSchema):
|
|||
providerName = schema.TextLine(
|
||||
title=_(u'Provider name'),
|
||||
description=_(u'The name of a utility that provides the '
|
||||
'external objects; default is a directory '
|
||||
'collection provider'),
|
||||
u'external objects; default is a directory '
|
||||
u'collection provider'),
|
||||
required=False)
|
||||
baseAddress = schema.TextLine(
|
||||
title=_(u'Base address'),
|
||||
description=_(u'A base path or URL for accessing this collection '
|
||||
'on the external system'),
|
||||
u'on the external system'),
|
||||
required=True)
|
||||
address = schema.TextLine(
|
||||
title=_(u'Relative address'),
|
||||
|
@ -66,7 +66,13 @@ class IExternalCollection(IConceptSchema):
|
|||
pattern = schema.TextLine(
|
||||
title=_(u'Selection pattern'),
|
||||
description=_(u'A regular expression for selecting external objects '
|
||||
'that should belong to this collection'),
|
||||
u'that should belong to this collection'),
|
||||
required=False)
|
||||
exclude = schema.List(
|
||||
title=_(u'Exclude'),
|
||||
description=_(u'Names of directories and files that should not '
|
||||
u'be included.'),
|
||||
value_type=schema.TextLine(),
|
||||
required=False)
|
||||
lastUpdated = Attribute('Date and time of last update.')
|
||||
|
||||
|
@ -93,9 +99,12 @@ class IExternalCollectionProvider(Interface):
|
|||
IExternalCollection interface.
|
||||
"""
|
||||
|
||||
def createExtFileObjects(clientCollection, addresses, extFileType=None):
|
||||
""" Create a resource of type 'extFileType' (default is the
|
||||
type with the name 'extfile') for each of the addresses
|
||||
provided. Return the list of objects created.
|
||||
def createExtFileObjects(clientCollection, addresses, extFileTypes=None):
|
||||
""" Create a resource for each of the addresses provided.
|
||||
Return the list of objects created.
|
||||
|
||||
The ``extFileTypes`` argument is a mapping of MIME types to
|
||||
names of concept types. The MIME types may contain wildcards,
|
||||
e.g. 'image/*', '*/*'.
|
||||
"""
|
||||
|
||||
|
|
|
@ -69,13 +69,22 @@ class MediaAsset(MediaAssetFile, ExternalFileAdapter):
|
|||
self.transform(self.rules)
|
||||
data = property(ExternalFileAdapter.getData, setData)
|
||||
|
||||
def setExternalAddress(self, addr):
|
||||
ExternalFileAdapter.setExternalAddress(self, addr)
|
||||
if addr and self.getMimeType().startswith('image/'):
|
||||
self.transform(self.rules)
|
||||
externalAddress = property(ExternalFileAdapter.getExternalAddress,
|
||||
setExternalAddress)
|
||||
|
||||
def getMimeType(self):
|
||||
return self.context.contentType or ''
|
||||
|
||||
def getDataPath(self):
|
||||
storage = component.getUtility(IExternalStorage, name=self.storageName)
|
||||
#print '***', self.storageName, self.storageParams, self.options
|
||||
return storage.getDir(self.externalAddress,
|
||||
self.options['storage_parameters'])
|
||||
#self.options['storage_parameters'])
|
||||
self.storageParams['subdirectory'])
|
||||
|
||||
def getOriginalData(self):
|
||||
return ExternalFileAdapter.getData(self)
|
||||
|
|
|
@ -275,7 +275,8 @@ class Resource(Image, Contained):
|
|||
oldAdapted.data = '' # clear old storage
|
||||
context._storageName = None # let's take storage from new type options
|
||||
context._storageParams = None # "
|
||||
newAdapted.data = data
|
||||
if data: # do not write empty files
|
||||
newAdapted.data = data
|
||||
|
||||
|
||||
# Document and MediaAsset are legacy classes, will become obsolete
|
||||
|
|
|
@ -72,9 +72,13 @@
|
|||
description row/description">
|
||||
<tr tal:attributes="class class">
|
||||
<td>
|
||||
<a tal:attributes="href string:${view/url}/.target${row/uniqueId}?version=this;
|
||||
title description"
|
||||
tal:content="row/title" />
|
||||
<a tal:attributes="href
|
||||
string:${view/url}/.target${row/uniqueId}?version=this;
|
||||
title description">
|
||||
<img tal:define="icon row/icon"
|
||||
tal:condition="icon"
|
||||
tal:attributes="src icon/src" />
|
||||
<div tal:content="row/title" /></a>
|
||||
</td>
|
||||
<td i18n:translate=""
|
||||
tal:content="row/longTypeTitle|row/typeTitle">Type</td>
|
||||
|
|
Loading…
Add table
Reference in a new issue