Skip to content

Commit

Permalink
Remove dependency on five.grok (#634)
Browse files Browse the repository at this point in the history
closes #510
  • Loading branch information
l34marr authored and hvelarde committed Aug 17, 2016
1 parent dfd128a commit 58844b8
Show file tree
Hide file tree
Showing 38 changed files with 1,081 additions and 1,056 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ install:
- bin/buildout
before_script:
- export DISPLAY=:99.0
- export GROK_DISABLE_TEMPLATE_WARNING=on
- sh -e /etc/init.d/xvfb start
- firefox -v
script:
Expand Down
11 changes: 11 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ There's a frood who really knows where his towel is.
1.2b2 (unreleased)
^^^^^^^^^^^^^^^^^^

.. Warning::
A huge code refactoring was made as part of the removal of the dependency on five.grok.
The following unused views were removed: ``AddCTWidget``, ``AddTileWidget``, ``SetWidgetMap``, ``UpdateWidget`` and ``RemoveTileWidget``.
All Compose tab helper views use now ``cmf.ModifyPortalContent`` permission.
All Layout tab helper views use now ``collective.cover.CanEditLayout`` permission.
The ``BaseGrid`` class is now located in the ``collective.cover.grids`` module.

- Remove dependency on five.grok (closes `#510`_).
[l34marr, rodfersou]

- Use the `X-Robots-Tag` header to avoid indexing of image scales on default view;
this will reduce the number of 404 (Not Found) responses generated by crawlers visiting the site in search of volatile content.
[hvelarde]
Expand Down Expand Up @@ -97,6 +107,7 @@ Previous entries can be found in the HISTORY.rst file.

.. _`#414`: https://github.com/collective/collective.cover/issues/414
.. _`#487`: https://github.com/collective/collective.cover/issues/487
.. _`#510`: https://github.com/collective/collective.cover/issues/510
.. _`#543`: https://github.com/collective/collective.cover/issues/543
.. _`#574`: https://github.com/collective/collective.cover/issues/574
.. _`#578`: https://github.com/collective/collective.cover/issues/578
Expand Down
22 changes: 16 additions & 6 deletions docs/developer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,13 @@ To do so, your theme package should provide a new grid system class which implem
from collective.cover.interfaces import IGridSystem
from collective.cover.layout import BaseGrid
from five import grok
from zope.interface import implementer
class MyGrid(BaseGrid, grok.GlobalUtility):
@implementer(IGridSystem)
class MyGrid(BaseGrid):
"""Bootstrap 3 grid system for small devices (12 columns)."""
grok.name('mygrid')
grok.implements(IGridSystem)
ncolumns = 12
title = _(u'MyGrid')
Expand All @@ -264,6 +262,12 @@ To do so, your theme package should provide a new grid system class which implem
)
return columns
Don't forget to register the utility in your ``configure.zcml``:

.. code-block:: xml
<utility name="mygrid" factory="my.package.MyGrid" />
Once registered you can select your grid system on the Cover Settings control panel configlet.

.. WARNING::
Expand Down Expand Up @@ -296,4 +300,10 @@ make sure you clear the default cover layouts and/or save your own layout with t
Custom Cover Views
^^^^^^^^^^^^^^^^^^

In case you want to create custom cover views, you can find the existing ones under browser/cover.py. Note that from version 1.0a12 collective.cover uses plone.app.blocks 2.0.0, which means that a cover view (or any view that includes tiles), must implement plone.app.blocks.interfaces.IBlocksTransformEnabled (using five.grok.implements(), zope.interface.implements() or @zope.interface.implementer()) within it's view class. Without this the resulting HTML would only contain tile placeholders, not the tiles themselves.
In case you want to create custom cover views,
you can find the existing ones under ``browser/cover.py``.
Note that from version 1.0a12 collective.cover uses plone.app.blocks 2.0.0,
which means that a cover view (or any view that includes tiles),
must implement ``plone.app.blocks.interfaces.IBlocksTransformEnabled`` (using ``@zope.interface.implementer()``) within it's view class.
Without this the resulting HTML would only contain tile placeholders,
not the tiles themselves.
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@
'collective.js.galleria',
'collective.js.jqueryui',
'collective.z3cform.datetimewidget',
'five.grok',
'Missing',
'plone.api >=1.4.11',
'plone.app.blocks >=2.2.1',
'plone.app.dexterity [grok, relations]',
'plone.app.dexterity [relations]',
'plone.app.iterate',
'plone.app.jquery >=1.7.2',
'plone.app.jquerytools >=1.5.1',
Expand Down
1 change: 1 addition & 0 deletions src/collective/cover/browser/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-

from Acquisition import aq_inner
from Products.CMFPlone.browser.ploneview import Plone

Expand Down
187 changes: 187 additions & 0 deletions src/collective/cover/browser/compose.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# -*- coding: utf-8 -*-
from collective.cover.tiles.list import IListTile
from plone import api
from plone.app.blocks.interfaces import IBlocksTransformEnabled
from plone.app.uuid.utils import uuidToObject
from plone.dexterity.events import EditBegunEvent
from plone.tiles.interfaces import ITileDataManager
from plone.uuid.interfaces import IUUID
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zExceptions import BadRequest
from zope.event import notify
from zope.interface import implementer


# TODO: implement EditCancelledEvent and EditFinishedEvent
# we need to leave the view after saving or cancelling editing
@implementer(IBlocksTransformEnabled)
class Compose(BrowserView):

"""Compose Tab."""

index = ViewPageTemplateFile('templates/compose.pt')

def __call__(self):
# lock the object when someone is editing it
notify(EditBegunEvent(self.context))
return self.index()


class UpdateTileContent(BrowserView):

"""Helper browser view to update the content of a tile."""

def setup(self):
self.tile_type = self.request.form.get('tile-type')
self.tile_id = self.request.form.get('tile-id')
self.uuid = self.request.form.get('uuid')

def render(self):
"""Render a tile after populating it with an object."""
if not all((self.tile_type, self.tile_id, self.uuid)):
raise BadRequest('Invalid parameters')

catalog = api.portal.get_tool('portal_catalog')
results = catalog(UID=self.uuid)
assert len(results) in (0, 1)
if results:
obj = results[0].getObject()
path = '{0}/{1}'.format(self.tile_type, self.tile_id)
tile = self.context.restrictedTraverse(path)
tile.populate_with_object(obj)
return tile()

def __call__(self):
self.setup()
return self.render()


class MoveTileContent(BrowserView):

"""Helper browser view to move the content from one tile to another."""

def _move_all_content(self, origin_tile, target_tile):
"""Move all content from one tile to another tile"""
# copy data
origin_dmgr = ITileDataManager(origin_tile)
origin_data = origin_dmgr.get()
if origin_data.get('uuids', None) is None:
return
target_dmgr = ITileDataManager(target_tile)
target_dmgr.set(origin_dmgr.get())
# remove origin tile
origin_dmgr.delete()

def _move_selected_content(self, origin_tile, target_tile, obj):
"""Move selected content from one tile to another tile"""
target_tile.populate_with_object(obj)
if IListTile.providedBy(origin_tile):
uuid = IUUID(obj)
origin_tile.remove_item(uuid)
else:
origin_dmgr = ITileDataManager(origin_tile)
origin_data = origin_dmgr.get()
target_dmgr = ITileDataManager(target_tile)
target_data = target_dmgr.get()
for k, v in origin_data.iteritems():
if k in target_data and not k.startswith('uuid') and v is not None:
target_data[k] = v
target_dmgr.set(target_data)
origin_dmgr.delete()

def setup(self):
self.origin_type = self.request.form.get('origin-type')
self.origin_id = self.request.form.get('origin-id')
self.target_type = self.request.form.get('target-type')
self.target_id = self.request.form.get('target-id')

def render(self):
"""Render a tile after populating it with an object."""
if not all((self.origin_type, self.origin_id, self.target_type, self.target_id)):
raise BadRequest('Invalid parameters')

origin_tile = self.context.restrictedTraverse(
'{0}/{1}'.format(self.origin_type, self.origin_id))
target_tile = self.context.restrictedTraverse(
'{0}/{1}'.format(self.target_type, self.target_id))
uuid = self.request.form.get('uuid')
obj = uuidToObject(uuid)
if obj is None:
self._move_all_content(origin_tile, target_tile)
else:
self._move_selected_content(origin_tile, target_tile, obj)
return target_tile()

def __call__(self):
self.setup()
return self.render()


class UpdateListTileContent(BrowserView):

"""Helper browser view to update the content of a list based tile."""

def setup(self):
self.tile_type = self.request.form.get('tile-type')
self.tile_id = self.request.form.get('tile-id')
self.uuids = self.request.form.get('uuids[]', [])
if type(self.uuids) is not list:
self.uuids = [self.uuids]

def render(self):
if not all((self.tile_type, self.tile_id, self.uuids)):
return u''

tile = self.context.restrictedTraverse(self.tile_type)
tile_instance = tile[self.tile_id]
tile_instance.replace_with_uuids(self.uuids)
return tile_instance()

def __call__(self):
self.setup()
return self.render()


class RemoveItemFromListTile(BrowserView):

"""Helper browser view to remove an object from a list tile."""

def setup(self):
self.tile_type = self.request.form.get('tile-type')
self.tile_id = self.request.form.get('tile-id')
self.uuid = self.request.form.get('uuid')

def render(self):
"""Render a tile after removing an object from it."""
if not all((self.tile_type, self.tile_id, self.uuid)):
raise BadRequest('Invalid parameters')

path = '{0}/{1}'.format(self.tile_type, self.tile_id)
tile = self.context.restrictedTraverse(path)
if IListTile.providedBy(tile):
tile.remove_item(self.uuid)
return tile()

def __call__(self):
self.setup()
return self.render()


class DeleteTile(BrowserView):

"""Helper browser view to remove a tile."""

def setup(self):
self.tile_type = self.request.form.get('tile-type')
self.tile_id = self.request.form.get('tile-id')

def render(self):
if self.tile_type and self.tile_id:
path = '{0}/{1}'.format(self.tile_type, self.tile_id)
tile = self.context.restrictedTraverse(path)
tile.delete()

def __call__(self):
self.setup()
return self.render()
Loading

0 comments on commit 58844b8

Please sign in to comment.