Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: customizing tabular view is hard #595

Closed
wants to merge 3 commits into from
Closed
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
5 changes: 2 additions & 3 deletions buildout.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ eggs =
recipe = zc.recipe.egg
eggs =
${test:eggs}
plone.app.robotframework[debug,ride,reload]
plone.app.robotframework[debug]


[releaser]
Expand All @@ -85,10 +85,9 @@ plone.app.contenttypes =
# Temporarily until next Plone version is out:
plone.app.querystring = 1.3.4

robotframework = 2.8.4
robotframework = 2.9.2
robotframework-ride = 1.3
robotframework-selenium2library = 1.6.0
robotsuite = 1.6.1
selenium = 2.46.0
coverage = 3.7.1
pycodestyle = 2.3.1
1 change: 1 addition & 0 deletions news/customize-tabular.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enable customization of tabular_view via views for fields of contentlisting items.
1 change: 1 addition & 0 deletions plone/app/contenttypes/browser/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def album_folders(self):
"""
return self._album_results['folders']

@property
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks for anyone who currently calls view.tabular_fields() in custom code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right !

def tabular_fields(self):
"""Returns a list of all metadata fields from the catalog that were
selected.
Expand Down
16 changes: 16 additions & 0 deletions plone/app/contenttypes/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,20 @@
<browser:page name="thumbnail_view" template="templates/listing_album.pt"/>
</browser:pages>

<browser:page
name="Title"
for="plone.app.contentlisting.interfaces.IContentListingObject"
class=".tabular.TitleCell"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
permission="zope2.View"
/>

<browser:page
name="Creator"
for="plone.app.contentlisting.interfaces.IContentListingObject"
class=".tabular.CreatorCell"
layer="plone.app.contenttypes.interfaces.IPloneAppContenttypesLayer"
permission="zope2.View"
/>

</configure>
32 changes: 32 additions & 0 deletions plone/app/contenttypes/browser/folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from zope.component import getMultiAdapter
from zope.component import getUtility
from zope.contentprovider.interfaces import IContentProvider
from zope.component import queryMultiAdapter
from zope.i18n import translate

import random

Expand All @@ -31,6 +33,7 @@ class FolderView(BrowserView):
_plone_view = None
_portal_state = None
_pas_member = None
_image_scale = None

@property
def plone_view(self):
Expand All @@ -50,6 +53,16 @@ def portal_state(self):
)
return self._portal_state

@property
def image_scale(self):
if not self._image_scale:
portal = self.portal_state.portal()
self._image_scale = getMultiAdapter(
(portal, self.request),
name=u'image_scale'
)
return self._image_scale

@property
def pas_member(self):
if not self._pas_member:
Expand Down Expand Up @@ -189,6 +202,21 @@ def tabular_fielddata(self, item, fieldname):
'value': value
}

def render_cells(self, item):
result = []
for field in self.tabular_fields:
if field == 'getIcon':
continue
cell_view = queryMultiAdapter((item, self.request), name=field)
if cell_view is not None:
cell_view.table_view = self
result.append(cell_view())
else:
field_data = self.tabular_fielddata(item, field)
value = translate(field_data['value'], context=self.request)
result.append('<td>%s</td>' % value)
return ''.join(result)

def is_event(self, obj):
if getattr(obj, 'getObject', False):
obj = obj.getObject()
Expand Down Expand Up @@ -265,6 +293,10 @@ def get_thumb_scale_table(self):
return None
return settings.thumb_scale_table

@property
def img_class(self):
return 'thumb-%s pull-right' % self.get_thumb_scale_table()

@memoize
def get_thumb_scale_list(self):
if getattr(self.context, 'suppress_thumbs', False):
Expand Down
55 changes: 55 additions & 0 deletions plone/app/contenttypes/browser/tabular.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from Products.Five import BrowserView

# BEWARE: the cell views are registered for ContentListingObject
# which are not acquisition aware.
# That precludes using Products.Five.ViewPageTemplateFile
# and imposes to use zope.browserpage.viewpagetemplatefile.
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
# BEWARE

class TitleCell(BrowserView):
__call__ = ViewPageTemplateFile('templates/titlecell.pt')

@property
def title(self):
return self.context.Title() or self.context.getId()

@property
def link(self):
suffix = (
'/view'
if self.context.PortalType in self.table_view.use_view_action
else ''
)
return self.context.getURL() + suffix

@property
def type_class(self):
return ('contenttype-' +
self.table_view.normalizeString(self.context.PortalType())
if self.table_view.show_icons else '')

@property
def wf_state_class(self):
return ('state-' +
self.table_view.normalizeString(self.context.review_state()))

def render_image(self):
thumb_scale_table = self.table_view.get_thumb_scale_table()
img_class = self.table_view.img_class
return self.table_view.image_scale.tag(
self.context, 'image',
scale=thumb_scale_table, css_class=img_class
)


class CreatorCell(BrowserView):
__call__ = ViewPageTemplateFile('templates/creatorcell.pt')

@property
def author(self):
return self.table_view.pas_member.info(self.context.Creator)

@property
def author_name(self):
return self.author['fullname'] or self.author['username']
5 changes: 5 additions & 0 deletions plone/app/contenttypes/browser/templates/creatorcell.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<td>
<a tal:condition="view/author"
tal:attributes="href string:${view/table_view/navigation_root_url}/author/${context/Creator}"
tal:content="view/author_name">Jos Henken</a>
</td>
50 changes: 2 additions & 48 deletions plone/app/contenttypes/browser/templates/listing_tabular.pt
Original file line number Diff line number Diff line change
Expand Up @@ -43,57 +43,11 @@
<tbody tal:define="portal context/@@plone_portal_state/portal;
image_scale portal/@@image_scale">
<tal:entries tal:repeat="item batch">
<tal:block tal:define="item_url item/getURL;
item_id item/getId;
item_title item/Title;
item_title python:item_title or item_id;
item_description item/Description;
item_type item/PortalType;
item_type_class python:'contenttype-' + view.normalizeString(item_type) if showicons else '';
item_wf_state item/review_state;
item_wf_state_class python:'state-' + view.normalizeString(item_wf_state);
item_creator item/Creator;
item_has_image python:item.getIcon;
item_link python:item_type in view.use_view_action and item_url+'/view' or item_url;
">
<tr metal:define-macro="listitem"
tal:define="oddrow repeat/item/odd;"
tal:attributes="class python: oddrow and 'even' or 'odd'">

<tal:block tal:repeat="field view/tabular_fields">
<td tal:condition="python:field not in ['Title', 'Creator', 'getIcon']"
tal:define="field_data python:view.tabular_fielddata(item, field)">
<tal:block tal:replace="field_data/value" />
</td>
<td tal:condition="python:field == 'Title'">
<a tal:condition="python:item_type == 'File' and showicons"
tal:attributes="href item_link;
class string:$item_type_class $item_wf_state_class url;
title item_type">
<img class="mime-icon"
tal:attributes="src item/MimeTypeIcon">
</a>
<a tal:attributes="href item_link;
class string:$item_type_class $item_wf_state_class url;
title item_type"
tal:content="item_title">Item Title
</a>
<a tal:condition="python:item_has_image and thumb_scale_table">
<img tal:attributes="href item_link"
tal:replace="structure python:image_scale.tag(item, 'image', scale=thumb_scale_table, css_class=img_class)" />
</a>
</td>
<td tal:condition="python:field == 'Creator'"
tal:define="author python:view.pas_member.info(item_creator);
name python:author['fullname'] or author['username']">
<a tal:condition="author"
tal:attributes="href string:${view/navigation_root_url}/author/${item_creator}"
tal:content="name">Jos Henken</a>
</td>
</tal:block>

tal:attributes="class python: oddrow and 'even' or 'odd'"
tal:content="structure python:view.render_cells(item)">
</tr>
</tal:block>
</tal:entries>
</tbody>
</table>
Expand Down
19 changes: 19 additions & 0 deletions plone/app/contenttypes/browser/templates/titlecell.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<td tal:define="table_view nocall:view/table_view;
thumb_scale_table view/table_view/get_thumb_scale_table;">
<a tal:condition="python:context.PortalType == 'File' and table_view.show_icons()"
tal:attributes="href view/link;
class string:${view/type_class} ${view/wf_state_class} url;
title context/PortalType">
<img class="mime-icon"
tal:attributes="src context/MimeTypeIcon">
</a>
<a tal:attributes="href view/link;
class string:${view/type_class} ${view/wf_state_class} url;
title context/PortalType"
tal:content="view/title">Item Title
</a>
<a tal:condition="python:context.getIcon and thumb_scale_table">
<img tal:attributes="href view/link"
tal:replace="structure view/render_image" />
</a>
</td>