Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions news/3953.breaking
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Move plone.app.contenttypes views to plone.app.layout
[frapell]
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
python_requires=">=3.10",
install_requires=[
"plone.app.content",
"plone.app.contenttypes",
"plone.app.dexterity",
"plone.app.linkintegrity",
"plone.app.relationfield",
Expand Down
1 change: 1 addition & 0 deletions src/plone/app/layout/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
directory="profiles/uninstall"
/>

<include package=".contenttypes" />
<include package=".globals" />
<include package=".navigation" />
<include package=".viewlets" />
Expand Down
Empty file.
85 changes: 85 additions & 0 deletions src/plone/app/layout/contenttypes/collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from Acquisition import aq_inner
from plone.app.contenttypes import _
from plone.app.contenttypes.behaviors.collection import ICollection
from plone.app.contenttypes.behaviors.leadimage import ILeadImage
from plone.app.contenttypes.interfaces import IFolder
from plone.app.contenttypes.interfaces import IImage
from plone.app.layout.contenttypes.folder import FolderView
from plone.memoize.view import memoize


class CollectionView(FolderView):
@property
def collection_behavior(self):
return ICollection(aq_inner(self.context))

@property
def b_size(self):
return getattr(self, "_b_size", self.collection_behavior.item_count)

def results(self, **kwargs):
"""Return a content listing based result set with results from the
collection query.

:param **kwargs: Any keyword argument, which can be used for catalog
queries.
:type **kwargs: keyword argument

:returns: plone.app.contentlisting based result set.
:rtype: ``plone.app.contentlisting.interfaces.IContentListing`` based
sequence.
"""
# Extra filter
contentFilter = dict(self.request.get("contentFilter", {}))
contentFilter.update(kwargs.get("contentFilter", {}))
kwargs.setdefault("custom_query", contentFilter)
kwargs.setdefault("batch", True)
kwargs.setdefault("b_size", self.b_size)
kwargs.setdefault("b_start", self.b_start)

results = self.collection_behavior.results(**kwargs)
return results

def batch(self):
# collection is already batched.
return self.results()

@property
@memoize
def _album_results(self):
"""Get results to display an album with subalbums."""
results = self.results()
images = []
folders = []
for it in results:
# TODO: potentially expensive!
ob = it.getObject()
if IFolder.providedBy(ob):
folders.append(it)
elif IImage.providedBy(ob) or ILeadImage.providedBy(ob):
images.append(it)
return {"images": images, "folders": folders}

@property
def album_images(self):
"""Get all images within this collection."""
return self._album_results["images"]

@property
def album_folders(self):
"""Get all folders within this collection."""
return self._album_results["folders"]

def tabular_fields(self):
"""Return a list of all metadata fields from the catalog that were
selected.
"""
context = aq_inner(self.context)
wrapped = ICollection(context)
fields = wrapped.selectedViewFields()
fields = [field[0] for field in fields]
return fields

@property
def no_items_message(self):
return _("description_no_results_found", default="No results were found.")
226 changes: 226 additions & 0 deletions src/plone/app/layout/contenttypes/configure.zcml
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:z3c="http://namespaces.zope.org/z3c"
xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="plone"
>

<include package="plone.app.contentmenu" />

<!-- VIEWS FOR PLONE SITE ROOT -->
<browser:pages
for="plone.base.interfaces.IPloneSiteRoot"
class=".folder.FolderView"
permission="zope2.View"
>
<browser:page
name="listing_view"
template="templates/listing.pt"
menu="plone_displayviews"
title="Standard view"
/>
<browser:page
name="summary_view"
template="templates/listing_summary.pt"
menu="plone_displayviews"
title="Summary view"
/>
<browser:page
name="tabular_view"
template="templates/listing_tabular.pt"
menu="plone_displayviews"
title="Tabular view"
/>
<browser:page
name="full_view"
template="templates/full_view.pt"
menu="plone_displayviews"
title="All content"
/>
<browser:page
name="album_view"
template="templates/listing_album.pt"
menu="plone_displayviews"
title="Album view"
/>
</browser:pages>


<!-- VIEWS FOR FOLDERS -->
<browser:pages
for="plone.dexterity.interfaces.IDexterityContainer"
class=".folder.FolderView"
permission="zope2.View"
>
<browser:page
name="listing_view"
template="templates/listing.pt"
menu="plone_displayviews"
title="Standard view"
/>
<browser:page
name="summary_view"
template="templates/listing_summary.pt"
menu="plone_displayviews"
title="Summary view"
/>
<browser:page
name="tabular_view"
template="templates/listing_tabular.pt"
menu="plone_displayviews"
title="Tabular view"
/>
<browser:page
name="full_view"
template="templates/full_view.pt"
menu="plone_displayviews"
title="All content"
/>
<browser:page
name="album_view"
template="templates/listing_album.pt"
menu="plone_displayviews"
title="Album view"
/>
</browser:pages>


<!-- VIEWS FOR COLLECTION ITEM -->
<browser:page
name="listing_view"
for="plone.app.contenttypes.interfaces.ICollection"
class=".collection.CollectionView"
template="templates/listing.pt"
permission="zope2.View"
/>

<!-- VIEWS FOR ANYTHING WITH THE COLLECTION BEHAVIOR.
Note that these ignore other fields, but integrators should
create other templates if they want that. Or improve the
query view widget. -->
<browser:pages
for="plone.app.contenttypes.behaviors.collection.ISyndicatableCollection"
class=".collection.CollectionView"
permission="zope2.View"
>
<browser:page
name="listing_view"
template="templates/listing.pt"
menu="plone_displayviews"
title="Standard view"
/>
<browser:page
name="summary_view"
template="templates/listing_summary.pt"
menu="plone_displayviews"
title="Summary view"
/>
<browser:page
name="tabular_view"
template="templates/listing_tabular.pt"
menu="plone_displayviews"
title="Tabular view"
/>
<browser:page
name="full_view"
template="templates/full_view.pt"
menu="plone_displayviews"
title="All content"
/>
<browser:page
name="album_view"
template="templates/listing_album.pt"
menu="plone_displayviews"
title="Album view"
/>
</browser:pages>


<!-- OTHER VIEWS -->
<browser:page
name="full_view_item"
for="*"
class=".full_view.FullViewItem"
template="templates/full_view_item.pt"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
/>
<browser:page
name="document_view"
template="templates/document.pt"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
menu="plone_displayviews"
title="View Document"
/>
<browser:page
name="file_view"
for="plone.app.contenttypes.interfaces.IFile"
class=".file.FileView"
template="templates/file.pt"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
menu="plone_displayviews"
title="View File"
/>
<browser:page
name="image_view"
for="plone.app.contenttypes.interfaces.IImage"
template="templates/image.pt"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
menu="plone_displayviews"
title="View Image"
/>
<browser:page
name="image_view_fullscreen"
for="plone.app.contenttypes.interfaces.IImage"
template="templates/image_view_fullscreen.pt"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
menu="plone_displayviews"
title="View Image Fullscreen"
/>
<browser:page
name="link_redirect_view"
for="plone.app.contenttypes.interfaces.ILink"
class=".link_redirect_view.LinkRedirectView"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
menu="plone_displayviews"
title="View Link"
/>
<browser:page
name="newsitem_view"
for="plone.app.contenttypes.interfaces.INewsItem"
template="templates/newsitem.pt"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
menu="plone_displayviews"
title="View News Item"
/>
<browser:page
name="contenttype_utils"
for="*"
class=".utils.Utils"
allowed_interface="plone.app.layout.contenttypes.utils.IUtils"
permission="zope2.View"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
/>

<browser:page
name="base_class_migrator_form"
for="plone.base.interfaces.IPloneSiteRoot"
class="plone.app.layout.contenttypes.migration.BaseClassMigrator"
permission="cmf.ManagePortal"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
/>

<utility
factory="plone.app.layout.contenttypes.migration.ChangedBaseClasses"
provides="zope.schema.interfaces.IVocabularyFactory"
name="plone.app.contenttypes.migration.changed_base_classes"
/>

</configure>
33 changes: 33 additions & 0 deletions src/plone/app/layout/contenttypes/file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from plone.app.layout.contenttypes.utils import Utils
from plone.base.utils import human_readable_size

import re


class FileView(Utils):
def is_videotype(self):
ct = self.context.file.contentType
return "video/" in ct

def is_audiotype(self):
ct = self.context.file.contentType
return "audio/" in ct

def human_readable_size(self):
return human_readable_size(self.context.file.getSize())

def icon(self):
if "text" in self.context.file.contentType:
return "contenttype-text"
if "html" in self.context.file.contentType:
return "contenttype-text"
if re.search(r"(archive|zip|compressed)", self.context.file.contentType):
return "contenttype-archive"
if "audio" in self.context.file.contentType:
return "contenttype-audio"
if "video" in self.context.file.contentType:
return "contenttype-video"
if "pdf" in self.context.file.contentType:
return "contenttype-pdf"
else:
return "contenttype-file"
Loading
Loading