Skip to content

Commit

Permalink
Merge 5519bd0 into e101065
Browse files Browse the repository at this point in the history
  • Loading branch information
hvelarde committed May 25, 2015
2 parents e101065 + 5519bd0 commit 28b1231
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ There's a frood who really knows where his towel is.
1.0a2 (unreleased)
------------------

- Add control panel configlet to define global options for the Cycle2 slideshow plugin (closes `#3`_).
[hvelarde]

- Remove browser layer and JS resource registry registrations.
Include all Cycle2 and plugins code as browser resources (closes `#1`_).
[rodfersou]
Expand All @@ -17,3 +20,4 @@ There's a frood who really knows where his towel is.
- Initial release.

.. _`#1`: https://github.com/collective/collective.js.cycle2/issues/1
.. _`#3`: https://github.com/collective/collective.js.cycle2/issues/3
8 changes: 8 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,25 @@
zip_safe=False,
install_requires=[
'plone.api',
'plone.app.registry',
'plone.directives.form',
'Products.CMFPlone >=4.2',
'Products.GenericSetup',
'setuptools',
'zope.i18nmessageid',
'zope.interface',
'zope.schema',
],
extras_require={
'test': [
'AccessControl',
'plone.app.robotframework',
'plone.app.testing [robot] >=4.2.2',
'plone.browserlayer',
'plone.registry',
'plone.testing',
'robotsuite',
'zope.component',
],
},
entry_points="""
Expand Down
11 changes: 11 additions & 0 deletions src/collective/js/cycle2/Extensions/Install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
from collective.js.cycle2.config import PROJECTNAME
from plone import api


def uninstall(portal, reinstall=False):
if not reinstall:
profile = 'profile-%s:uninstall' % PROJECTNAME
setup_tool = api.portal.get_tool('portal_setup')
setup_tool.runAllImportStepsFromProfile(profile)
return 'Ran all uninstall steps.'
1 change: 1 addition & 0 deletions src/collective/js/cycle2/Extensions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
3 changes: 3 additions & 0 deletions src/collective/js/cycle2/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
# -*- coding: utf-8 -*-
from zope.i18nmessageid import MessageFactory

_ = MessageFactory('collective.js.cycle2')
2 changes: 2 additions & 0 deletions src/collective/js/cycle2/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
PROJECTNAME = 'collective.js.cycle2'
19 changes: 19 additions & 0 deletions src/collective/js/cycle2/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

<five:registerPackage package="." />

<include package="Products.CMFCore" file="permissions.zcml" />
<include package="plone.directives.form" file="meta.zcml" />
<include package="plone.directives.form" />

<genericsetup:registerProfile
name="default"
title="collective.js.cycle2"
Expand All @@ -15,6 +19,21 @@
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

<genericsetup:registerProfile
name="uninstall"
title="collective.js.cycle2"
directory="profiles/uninstall"
description="Uninstall profile for the collective.js.cycle2 package."
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

<browser:page
name="cycle2-settings"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".controlpanel.Cycle2SettingsControlPanel"
permission="cmf.ManagePortal"
/>

<browser:resourceDirectory name="collective.js.cycle2" directory="resources" />

<include package=".upgrades" />
Expand Down
88 changes: 88 additions & 0 deletions src/collective/js/cycle2/controlpanel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
from collective.js.cycle2 import _
from plone.app.registry.browser import controlpanel
from plone.directives import form
from zope import schema
from zope.schema.vocabulary import SimpleTerm
from zope.schema.vocabulary import SimpleVocabulary

fx = ['fade', 'fadeout', 'none', 'scrollHorz']
fx = SimpleVocabulary([SimpleTerm(f) for f in fx])

# TODO: get this from portal_properties/imaging_properties
scales = ['large', 'preview', 'mini', 'thumb', 'tile', 'icon', 'listing']
scales = SimpleVocabulary([SimpleTerm(s) for s in scales])


class ICycle2Settings(form.Schema):

"""Interface for the control panel form."""

paused = schema.Bool(
title=_(u'Paused'),
description=_(u'If selected the slideshow will begin in a paused state.'),
default=True,
)

allow_wrap = schema.Bool(
title=_(u'Allow wrap'),
description=_(u'Determines whether or not a slideshow can advance from the last slide to the first (or vice versa).'),
default=True,
)

caption_template = schema.TextLine(
title=_(u'Caption Template'),
description=_(
u'A template string which defines how the slideshow caption should be formatted. '
u'',
),
default=u'{{slideNum}} / {{slideCount}}',
)

pager_template = schema.TextLine(
title=_(u'Pager Template'),
description=_(
u'A template string which defines how the pager links should be formatted. '
u'',
),
default=u'<span>&bull;</span>',
)

speed = schema.Int(
title=_(u'Speed'),
description=_(u'The speed of the transition effect in milliseconds.'),
default=500,
)

timeout = schema.Int(
title=_(u'Timeout'),
description=_(u'The time between slide transitions in milliseconds.'),
default=4000,
)

transition_effect = schema.Choice(
title=_(u'Transition effect'),
description=_(u'The name of the slideshow transition to use.'),
required=True,
vocabulary=fx,
default='fade',
)

default_image_size = schema.Choice(
title=_(u'Default Image Size'),
description=_(u''),
required=True,
vocabulary=scales,
default='preview',
)


class Cycle2SettingsEditForm(controlpanel.RegistryEditForm):
schema = ICycle2Settings
label = _(u'Cycle2')
description = _(
u'Here you can define global configuration options for the Cycle2 slideshow plugin.')


class Cycle2SettingsControlPanel(controlpanel.ControlPanelFormWrapper):
form = Cycle2SettingsEditForm
17 changes: 17 additions & 0 deletions src/collective/js/cycle2/profiles/default/controlpanel.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<object name="portal_controlpanel"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="collective.js.cycle2"
purge="False">
<configlet title="Cycle2"
action_id="cycle2"
appId="collective.js.cycle2"
category="Products"
condition_expr=""
url_expr="string:${portal_url}/@@cycle2-settings"
icon_expr="string:${portal_url}/++resource++collective.js.cycle2/cycle2-icon.png"
visible="True"
i18n:attributes="title">
<permission>Manage portal</permission>
</configlet>
</object>
4 changes: 4 additions & 0 deletions src/collective/js/cycle2/profiles/default/registry.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<registry>
<records interface="collective.js.cycle2.controlpanel.ICycle2Settings" />
</registry>
4 changes: 4 additions & 0 deletions src/collective/js/cycle2/profiles/uninstall/registry.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<registry>
<records interface="collective.js.cycle2.controlpanel.ICycle2Settings" remove="true" />
</registry>
1 change: 1 addition & 0 deletions src/collective/js/cycle2/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
108 changes: 108 additions & 0 deletions src/collective/js/cycle2/tests/test_controlpanel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
from collective.js.cycle2.config import PROJECTNAME
from collective.js.cycle2.controlpanel import ICycle2Settings
from collective.js.cycle2.testing import INTEGRATION_TESTING
from plone import api
from plone.app.testing import logout
from plone.registry.interfaces import IRegistry
from zope.component import getUtility

import unittest


class ControlPanelTestCase(unittest.TestCase):

layer = INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.controlpanel = self.portal['portal_controlpanel']

def test_controlpanel_has_view(self):
request = self.layer['request']
view = api.content.get_view(u'cycle2-settings', self.portal, request)
view = view.__of__(self.portal)
self.assertTrue(view())

def test_controlpanel_view_is_protected(self):
from AccessControl import Unauthorized
logout()
with self.assertRaises(Unauthorized):
self.portal.restrictedTraverse('@@cycle2-settings')

def test_controlpanel_installed(self):
actions = [a.getAction(self)['id']
for a in self.controlpanel.listActions()]
self.assertIn('cycle2', actions, 'control panel not installed')

def test_controlpanel_removed_on_uninstall(self):
qi = self.portal['portal_quickinstaller']

with api.env.adopt_roles(['Manager']):
qi.uninstallProducts(products=[PROJECTNAME])

actions = [a.getAction(self)['id']
for a in self.controlpanel.listActions()]
self.assertNotIn('cycle2', actions, 'control panel not removed')


class RegistryTestCase(unittest.TestCase):

layer = INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.registry = getUtility(IRegistry)
self.settings = self.registry.forInterface(ICycle2Settings)

def test_paused_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'paused'))
self.assertEqual(self.settings.paused, True)

def test_allow_wrap_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'allow_wrap'))
self.assertEqual(self.settings.allow_wrap, True)

def test_caption_template_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'caption_template'))
self.assertEqual(self.settings.caption_template, u'{{slideNum}} / {{slideCount}}')

def test_pager_template_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'pager_template'))
self.assertEqual(self.settings.pager_template, u'<span>&bull;</span>')

def test_speed_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'speed'))
self.assertEqual(self.settings.speed, 500)

def test_timeout_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'timeout'))
self.assertEqual(self.settings.timeout, 4000)

def test_transition_effect_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'transition_effect'))
self.assertEqual(self.settings.transition_effect, 'fade')

def test_default_image_size_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'default_image_size'))
self.assertEqual(self.settings.default_image_size, 'preview')

def test_records_removed_on_uninstall(self):
qi = self.portal['portal_quickinstaller']

with api.env.adopt_roles(['Manager']):
qi.uninstallProducts(products=[PROJECTNAME])

records = [
ICycle2Settings.__identifier__ + '.paused',
ICycle2Settings.__identifier__ + '.allow_wrap',
ICycle2Settings.__identifier__ + '.caption_template',
ICycle2Settings.__identifier__ + '.pager_template',
ICycle2Settings.__identifier__ + '.speed',
ICycle2Settings.__identifier__ + '.timeout',
ICycle2Settings.__identifier__ + '.transition_effect',
ICycle2Settings.__identifier__ + '.default_image_size',
]

for r in records:
self.assertNotIn(r, self.registry)
3 changes: 1 addition & 2 deletions src/collective/js/cycle2/tests/test_setup.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
from collective.js.cycle2.config import PROJECTNAME
from collective.js.cycle2.testing import INTEGRATION_TESTING

import unittest

PROJECTNAME = 'collective.js.cycle2'


class InstallTestCase(unittest.TestCase):

Expand Down

0 comments on commit 28b1231

Please sign in to comment.