-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #136 from syslabcom/scrum-1181-publicationlisting
Port publicationlisting viewlet
- Loading branch information
Showing
3 changed files
with
299 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
src/recensio/plone/viewlets/templates/publicationlisting.pt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<div id="publicationlisting" | ||
tal:define=" | ||
language context/@@plone_portal_state/language; | ||
portal_url context/portal_url; | ||
" | ||
tal:condition="view/visible" | ||
i18n:domain="recensio" | ||
> | ||
|
||
<a name="publicationslisting"></a> | ||
<tal:volumes repeat="volume view/volumes | nothing"> | ||
<div class="review_container" | ||
tal:define=" | ||
volume_expanded python:view.is_expanded(volume['UID']); | ||
is_container python:volume['css_classes'] and 'review_container' in volume['css_classes']; | ||
" | ||
tal:attributes=" | ||
id volume/UID; | ||
class volume/css_classes; | ||
" | ||
> | ||
<a class="container_trigger" | ||
href="#" | ||
tal:condition="is_container" | ||
tal:attributes=" | ||
href volume/toggle_link; | ||
" | ||
> | ||
<h2 tal:content="volume/Title"></h2> | ||
</a> | ||
<h2 tal:condition="not:is_container" | ||
tal:content="volume/Title" | ||
></h2> | ||
|
||
<span class="pdf" | ||
tal:condition="volume/pdf | nothing" | ||
> | ||
<a href="" | ||
tal:attributes=" | ||
href string:${volume/pdf}/at_download/file; | ||
" | ||
> | ||
<img alt="" | ||
src="pdf.png" | ||
/> | ||
<span i18n:translate="label_download_complete_pdf">download Gesamt-pdf</span> | ||
</a> | ||
<span class="discreet"> | ||
— | ||
<span>PDF</span>, | ||
<tal:size content="volume/pdfsize">?</tal:size> | ||
</span> | ||
</span> | ||
|
||
<ul tal:condition="is_container"> | ||
<li tal:condition="volume_expanded" | ||
tal:repeat="review python:view.reviews(volume=volume['id'])" | ||
> | ||
<a tal:content="review/getDecoratedTitle" | ||
tal:attributes=" | ||
href review/absolute_url; | ||
" | ||
></a> | ||
</li> | ||
</ul> | ||
</div> | ||
|
||
<tal:issues repeat="issue python:view.issues(volume=volume['id'])"> | ||
<div class="review_container" | ||
tal:define=" | ||
issue_expanded python:view.is_expanded(issue['UID']); | ||
is_container python:issue['css_classes'] and 'review_container' in issue['css_classes']; | ||
" | ||
tal:attributes=" | ||
id issue/UID; | ||
class issue/css_classes; | ||
" | ||
> | ||
<a class="container_trigger" | ||
href="#" | ||
tal:condition="is_container" | ||
tal:attributes=" | ||
href issue/toggle_link; | ||
" | ||
> | ||
<h3 tal:content="issue/Title"></h3> | ||
</a> | ||
<h3 tal:condition="not:is_container" | ||
tal:content="issue/Title" | ||
></h3> | ||
|
||
|
||
<span class="pdf" | ||
tal:condition="issue/pdf | nothing" | ||
> | ||
<a href="" | ||
tal:attributes=" | ||
href string:${issue/pdf}/at_download/file; | ||
" | ||
> | ||
<img alt="" | ||
src="pdf.png" | ||
/> | ||
<span i18n:translate="label_download_complete_pdf">download Gesamt-pdf</span> | ||
</a> | ||
<span class="discreet"> | ||
— | ||
<span>PDF</span>, | ||
<tal:size content="issue/pdfsize">?</tal:size> | ||
</span> | ||
</span> | ||
|
||
<tal:comment replace="nothing"> | ||
An image would be nicer, but not my expertise :( | ||
<img class="loading" | ||
src="++resource++recensio.theme.images/fancy_loading.png" | ||
tal:condition="is_container" | ||
tal:attributes=" | ||
src string:${context/portal_url}/++resource++recensio.theme.images/fancy_loading.png; | ||
" | ||
/> | ||
</tal:comment> | ||
<ul tal:condition="is_container"> | ||
<li tal:condition="issue_expanded" | ||
tal:repeat="review python:view.reviews(volume=volume['id'],issue=issue['id'])" | ||
> | ||
<a tal:content="review/getDecoratedTitle" | ||
tal:attributes=" | ||
href review/absolute_url; | ||
" | ||
></a> | ||
</li> | ||
</ul> | ||
</div> | ||
</tal:issues> | ||
</tal:volumes> | ||
|
||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
from DateTime import DateTime | ||
from plone import api | ||
from plone.app.layout.viewlets import ViewletBase | ||
from plone.memoize import ram | ||
from Products.CMFCore.utils import getToolByName | ||
from recensio.plone.adapter.indexer import listAuthorsAndEditors | ||
from zope.interface import implementer | ||
from zope.viewlet.interfaces import IViewlet | ||
from ZTUtils import make_query | ||
|
||
import logging | ||
|
||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def _render_cachekey(method, self, volume, issue=None): | ||
portal_membership = getToolByName(self.context, "portal_membership") | ||
member = portal_membership.getAuthenticatedMember() | ||
roles = member.getRolesInContext(self.context) | ||
today = DateTime().strftime("%Y-%m-%d") | ||
context_url = self.context.absolute_url() | ||
return (context_url, roles, today, volume, issue) | ||
|
||
|
||
@implementer(IViewlet) | ||
class Publicationlisting(ViewletBase): | ||
"""Lists Volumes/Issues/Reviews in the current Publication""" | ||
|
||
def __init__(self, context, request, view, manager=None): | ||
super().__init__(context, request, view, manager) | ||
try: | ||
parents = self.request.PARENTS | ||
except AttributeError: | ||
return False | ||
if len(parents) < 2: | ||
return False | ||
self.parent = self.request.PARENTS[1] | ||
|
||
def visible(self): | ||
"""should we display at all?""" | ||
if ( | ||
hasattr(self.context, "portal_type") | ||
and self.context.portal_type == "Document" | ||
and hasattr(self.parent, "portal_type") | ||
and self.parent.portal_type == "Publication" | ||
): | ||
return True | ||
return False | ||
|
||
def is_expanded(self, uid): | ||
return uid in self.request.get("expand", []) | ||
|
||
def _make_dict(self, obj): | ||
"contains the relevant details for listing a Review" | ||
view = api.content.get_view( | ||
context=obj, request=self.request, name="review_view" | ||
) | ||
return { | ||
"absolute_url": obj.absolute_url(), | ||
"effective": obj.effective(), | ||
"getDecoratedTitle": view.getDecoratedTitle(), | ||
"listAuthorsAndEditors": listAuthorsAndEditors(obj)(), | ||
"Title": obj.Title(), | ||
} | ||
|
||
def _get_toggle_link(self, uid): | ||
expand = self.request.get("expand", [])[:] | ||
if uid in expand: | ||
expand.remove(uid) | ||
else: | ||
expand.append(uid) | ||
toggle_link = "{}?{}#{}".format( | ||
self.context.absolute_url(), | ||
make_query(expand=expand), | ||
uid, | ||
) | ||
return toggle_link | ||
|
||
def _get_css_classes(self, obj): | ||
css_classes = [] | ||
reviews = [ | ||
obj | ||
for obj in obj.objectValues() | ||
if obj.portal_type in ("Review Monograph", "Review Journal") | ||
] | ||
if len(reviews) > 0: | ||
css_classes.append("review_container") | ||
if self.is_expanded(obj.UID()): | ||
css_classes.append("expanded") | ||
return " ".join(css_classes) or None | ||
|
||
def _make_iss_or_vol_dict(self, obj): | ||
issue_dict = { | ||
"Title": obj.Title(), | ||
"id": obj.getId(), | ||
"UID": obj.UID(), | ||
"toggle_link": self._get_toggle_link(obj.UID()), | ||
"css_classes": self._get_css_classes(obj), | ||
} | ||
|
||
if "issue.pdf" in obj.objectIds(): | ||
issue_dict["pdf"] = obj["issue.pdf"].absolute_url_path() | ||
issue_dict["pdfsize"] = self._formatsize(obj["issue.pdf"].file.size) | ||
return issue_dict | ||
|
||
def volumes(self): | ||
objects = self.parent.getFolderContents( | ||
{"portal_type": "Volume"}, full_objects=True | ||
) | ||
volume_objs = sorted(objects, key=lambda v: v.effective(), reverse=True) | ||
volumes = [self._make_iss_or_vol_dict(v) for v in volume_objs] | ||
return volumes | ||
|
||
def issues(self, volume): | ||
if volume not in self.parent: | ||
return [] | ||
objects = self.parent[volume].getFolderContents( | ||
{"portal_type": "Issue"}, full_objects=True | ||
) | ||
issue_objs = sorted(objects, key=lambda v: v.effective(), reverse=True) | ||
issues = [self._make_iss_or_vol_dict(i) for i in issue_objs] | ||
return issues | ||
|
||
@ram.cache(_render_cachekey) | ||
def reviews(self, volume, issue=None): | ||
if volume not in self.parent.objectIds(): | ||
return [] | ||
if issue is None: | ||
review_objs = self.parent[volume].getFolderContents( | ||
{"portal_type": ["Review Monograph", "Review Journal"]}, | ||
full_objects=True, | ||
) | ||
else: | ||
if issue not in self.parent[volume].objectIds(): | ||
return [] | ||
review_objs = self.parent[volume][issue].getFolderContents( | ||
{"portal_type": ["Review Monograph", "Review Journal"]}, | ||
full_objects=True, | ||
) | ||
review_objs = sorted(review_objs, key=lambda v: listAuthorsAndEditors(v)()) | ||
reviews = [self._make_dict(rev) for rev in review_objs] | ||
return reviews | ||
|
||
def _formatsize(self, size): | ||
size_kb = size / 1024 | ||
display_size_kb = f"{size_kb:n} kB" if size_kb > 0 else "" | ||
if display_size_kb: | ||
display_size_bytes = f" ({size:n} bytes)" | ||
else: | ||
display_size_bytes = f"{size:n} bytes" | ||
display_size = f"{display_size_kb}{display_size_bytes}" | ||
return display_size |