diff --git a/browser/common.py b/browser/common.py index 571df48..77b8080 100644 --- a/browser/common.py +++ b/browser/common.py @@ -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) diff --git a/browser/concept_macros.pt b/browser/concept_macros.pt index eb4faf4..c201d19 100644 --- a/browser/concept_macros.pt +++ b/browser/concept_macros.pt @@ -3,12 +3,14 @@
- - - - - - + + + + + + + +
@@ -154,7 +156,10 @@ - Resource Title + +
Resource Title
Type diff --git a/browser/resource.py b/browser/resource.py index b38876a..8ed2ff8 100644 --- a/browser/resource.py +++ b/browser/resource.py @@ -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: diff --git a/integrator/collection.py b/integrator/collection.py index 0adfd8f..1ab8bf1 100644 --- a/integrator/collection.py +++ b/integrator/collection.py @@ -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): diff --git a/integrator/collection_macros.pt b/integrator/collection_macros.pt index e824484..4ba39b3 100644 --- a/integrator/collection_macros.pt +++ b/integrator/collection_macros.pt @@ -1,11 +1,19 @@ - + - -
- -
+ -
+ + + +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/integrator/interfaces.py b/integrator/interfaces.py index ba2c0b5..32e9b16 100644 --- a/integrator/interfaces.py +++ b/integrator/interfaces.py @@ -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/*', '*/*'. """ diff --git a/media/asset.py b/media/asset.py index e576113..32e823b 100644 --- a/media/asset.py +++ b/media/asset.py @@ -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) diff --git a/resource.py b/resource.py index e678496..0cfe549 100644 --- a/resource.py +++ b/resource.py @@ -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 diff --git a/search/search.pt b/search/search.pt index eecffe8..0fdfe35 100644 --- a/search/search.pt +++ b/search/search.pt @@ -72,9 +72,13 @@ description row/description"> - + + +
Type