Skip to content

Commit

Permalink
Editing control panel replaced with plone.autoform form.
Browse files Browse the repository at this point in the history
  • Loading branch information
Timo Stollenwerk committed Mar 14, 2012
1 parent 2bd6441 commit 91d0c2f
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 13 deletions.
Empty file.
13 changes: 13 additions & 0 deletions plone/app/controlpanel/browser/configure.zcml
@@ -0,0 +1,13 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five"
xmlns:browser="http://namespaces.zope.org/browser">

<browser:page
name="editing-controlpanel"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".editing.EditingControlPanelView"
permission="plone.app.controlpanel.Editing"
/>

</configure>
33 changes: 33 additions & 0 deletions plone/app/controlpanel/browser/controlpanel_layout.pt
@@ -0,0 +1,33 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="here/prefs_main_template/macros/master"
i18n:domain="plone">

<body>

<div metal:fill-slot="prefs_configlet_main">

<a href=""
id="setup-link"
tal:attributes="href string:$portal_url/plone_control_panel"
i18n:translate="">
Site Setup
</a> &rsaquo;

<h1 class="documentFirstHeading" tal:content="view/label">View Title</h1>

<div metal:use-macro="context/global_statusmessage/macros/portal_message">
Portal status message
</div>

<div id="layout-contents">
<span tal:replace="structure view/contents" />
</div>

</div>

</body>
</html>
135 changes: 135 additions & 0 deletions plone/app/controlpanel/browser/editing.py
@@ -0,0 +1,135 @@
from zope.site.hooks import getSite
from Products.CMFCore.utils import getToolByName
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.statusmessages.interfaces import IStatusMessage
from z3c.form import button
from z3c.form import form
from plone.z3cform import layout

from zope.interface import Interface
from zope.schema import Bool
from zope.schema import Choice

from Products.CMFPlone import PloneMessageFactory as _

from plone.autoform.form import AutoExtensibleForm


class IEditingSchema(Interface):

visible_ids = Bool(
title=_(u"Show 'Short Name' on content?"),
description=_(u"Display and allow users to edit the "
"'Short name' content identifiers, which form the "
"URL part of a content item's address. Once "
"enabled, users will then be able to enable this "
"option in their preferences."),
default=False,
required=False)

default_editor = Choice(
title=_(u'Default editor'),
description=_(u"Select the default wysiwyg "
"editor. Users will be able to choose their "
"own or select to use the site default."),
default=u'TinyMCE',
missing_value=set(),
vocabulary="plone.app.vocabularies.AvailableEditors",
required=False)

ext_editor = Bool(
title=_(u'Enable External Editor feature'),
description=_(u"Determines if the external editor "
"feature is enabled. This feature requires a "
"special client-side application installed. The "
"users also have to enable this in their "
"preferences."),
default=False,
required=False)

enable_inline_editing = Bool(
title=_(u"Enable inline editing"),
description=_(u"Check this to enable "
"inline editing on the site."),
default=True,
required=False)

enable_link_integrity_checks = Bool(
title=_(u"Enable link integrity checks"),
description=_(u"Determines if the users should get "
"warnings when they delete or move content that "
"is linked from inside the site."),
default=True,
required=False)

lock_on_ttw_edit = Bool(
title=_(u"Enable locking for through-the-web edits"),
description=_(u"Disabling locking here will only "
"affect users editing content through the "
"Plone web UI. Content edited via WebDAV "
"clients will still be subject to locking."),
default=True,
required=False)


class EditingControlPanel(AutoExtensibleForm, form.EditForm):
schema = IEditingSchema
id = "editing-control-panel"
label = _("Editing settings")
description = _("General editing settings.")
form_name = _("Editing settings")
control_panel_view = "editing-controlpanel"

def getContent(self):
portal = getSite()
pprop = getToolByName(portal, 'portal_properties')
site_properties = pprop.site_properties
self.context = site_properties
context = dict()
context['visible_ids'] = site_properties.getProperty('visible_ids')
context['enable_inline_editing'] = \
site_properties.getProperty('enable_inline_editing')
context['enable_link_integrity_checks'] = \
site_properties.getProperty('enable_link_integrity_checks')
context['ext_editor'] = site_properties.getProperty('ext_editor')
context['default_editor'] = site_properties.getProperty('default_editor')
context['lock_on_ttw_edit'] = site_properties.getProperty('lock_on_ttw_edit')
return context

@button.buttonAndHandler(_('Save'), name='save')
def handleSave(self, action):
data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
portal = getSite()
pprop = getToolByName(portal, 'portal_properties')
site_properties = pprop.site_properties
site_properties.manage_changeProperties(
visible_ids=data['visible_ids'],
enable_inline_editing=data['enable_inline_editing'],
enable_link_integrity_checks=data['enable_link_integrity_checks'],
ext_editor=data['ext_editor'],
default_editor=data['default_editor'],
lock_on_ttw_edit=data['lock_on_ttw_edit'])
#IStatusMessage(self.request).addStatusMessage(_(u"Changes saved"),
#S "info")
self.request.response.redirect("@@editing-controlpanel")

@button.buttonAndHandler(_(u"Cancel"), name='cancel')
def handleCancel(self, action):
IStatusMessage(self.request).addStatusMessage(
_(u"Changes canceled."), "info")
self.request.response.redirect("plone_control_panel")


class ControlPanelFormWrapper(layout.FormWrapper):
"""Use this form as the plone.z3cform layout wrapper to get the control
panel layout.
"""

index = ViewPageTemplateFile('controlpanel_layout.pt')


EditingControlPanelView = layout.wrap_form(
EditingControlPanel, ControlPanelFormWrapper)
11 changes: 2 additions & 9 deletions plone/app/controlpanel/configure.zcml
Expand Up @@ -5,9 +5,9 @@

<include file="permissions.zcml"/>

<adapter factory=".calendar.CalendarControlPanelAdapter" />
<include package=".browser" />

<adapter factory=".editing.EditingControlPanelAdapter" />
<adapter factory=".calendar.CalendarControlPanelAdapter" />

<adapter factory=".filter.FilterControlPanelAdapter" />

Expand Down Expand Up @@ -40,13 +40,6 @@
permission="plone.app.controlpanel.Calendar"
/>

<browser:page
name="editing-controlpanel"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".editing.EditingControlPanel"
permission="plone.app.controlpanel.Editing"
/>

<browser:page
name="filter-controlpanel"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
Expand Down
27 changes: 27 additions & 0 deletions plone/app/controlpanel/testing.py
@@ -0,0 +1,27 @@
from plone.app.testing import PloneSandboxLayer
from plone.app.testing import applyProfile
from plone.app.testing import PLONE_FIXTURE
from plone.app.testing import IntegrationTesting
from plone.app.testing import FunctionalTesting

from zope.configuration import xmlconfig


class PloneAppControlpanel(PloneSandboxLayer):

defaultBases = (PLONE_FIXTURE,)

def setUpZope(self, app, configurationContext):
# Load ZCML
import plone.app.controlpanel
xmlconfig.file('configure.zcml',
plone.app.controlpanel,
context=configurationContext)

PLONE_APP_CONTROLPANEL_FIXTURE = PloneAppControlpanel()
PLONE_APP_CONTROLPANEL_INTEGRATION_TESTING = IntegrationTesting(
bases=(PLONE_APP_CONTROLPANEL_FIXTURE,),
name="PloneAppControlpanel:Integration")
PLONE_APP_CONTROLPANEL_FUNCTIONAL_TESTING = FunctionalTesting(
bases=(PLONE_APP_CONTROLPANEL_FIXTURE,),
name="PloneAppControlpanel:Functional")
10 changes: 6 additions & 4 deletions plone/app/controlpanel/tests/editing.txt
Expand Up @@ -17,7 +17,7 @@ Viewing the site control panel

Click the cancel button:

>>> self.browser.getControl(name="form.actions.cancel").click()
>>> self.browser.getControl(name="form.buttons.cancel").click()
>>> self.browser.url.endswith('plone_control_panel')
True

Expand All @@ -33,10 +33,12 @@ Configure the locking for the site
Standard behavior for locking is to have it enabled. Let's change that:

>>> self.browser.open('http://nohost/plone/@@editing-controlpanel')
>>> self.browser.getControl(name='form.lock_on_ttw_edit').value
>>> self.browser.getControl(name='form.widgets.lock_on_ttw_edit:list').value
['selected']
>>> self.browser.getControl(name='form.widgets.lock_on_ttw_edit:list').value = False
>>> self.browser.getControl(name="form.buttons.save").click()
>>> self.browser.url.endswith('editing-controlpanel')
True
>>> self.browser.getControl(name='form.lock_on_ttw_edit').value = False
>>> self.browser.getControl(name="form.actions.save").click()

Confirm that our change updated the property:

Expand Down
86 changes: 86 additions & 0 deletions plone/app/controlpanel/tests/test_editing.py
@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
import unittest2 as unittest

from zope.component import getMultiAdapter

from plone.app.controlpanel.browser.editing import EditingControlPanel

from zope.publisher.browser import TestRequest
from z3c.form.interfaces import IFormLayer

from Products.CMFCore.utils import getToolByName

from plone.app.testing import TEST_USER_ID, setRoles

from plone.app.controlpanel.testing import \
PLONE_APP_CONTROLPANEL_INTEGRATION_TESTING


class EditingControlPanelIntegrationTest(unittest.TestCase):

layer = PLONE_APP_CONTROLPANEL_INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])

def test_editing_controlpanel_view(self):
view = getMultiAdapter((self.portal, self.portal.REQUEST),
name="editing-controlpanel")
view = view.__of__(self.portal)
self.assertTrue(view())

def test_editing_in_controlpanel(self):
self.controlpanel = getToolByName(self.portal, "portal_controlpanel")
self.assertTrue('EditingSettings' in [a.getAction(self)['id']
for a in self.controlpanel.listActions()])


class EditingControlPanelFormTest(unittest.TestCase):

layer = PLONE_APP_CONTROLPANEL_INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.request = TestRequest(
environ={'AUTHENTICATED_USER': 'user1'},
form={
'form.widgets.visible_ids': 'true',
'form.widgets.enable_inline_editing': 'true',
'form.widgets.enable_link_integrity_checks': 'true',
'form.widgets.default_editor': "TinyMCE",
'form.widgets.lock_on_ttw_edit': "true",
'form.widgets.ext_editor': "true",
'form.buttons.save': 'true',
},
skin=IFormLayer)
ptool = getToolByName(self.portal, 'portal_properties')
self.site_properties = ptool.site_properties

def test_editing_control_panel_form(self):
editing_form = EditingControlPanel(self.portal, self.request)

editing_form.update()

self.assertTrue('visible_ids' in editing_form.fields.keys())
self.assertTrue('default_editor' in editing_form.fields.keys())
self.assertTrue('ext_editor' in editing_form.fields.keys())
self.assertTrue('enable_inline_editing' in editing_form.fields.keys())
self.assertTrue(
'enable_link_integrity_checks' in editing_form.fields.keys())
self.assertTrue('lock_on_ttw_edit' in editing_form.fields.keys())

def test_visible_ids_setting(self):
editing_form = EditingControlPanel(self.portal, self.request)

editing_form.update()
editing_form.handleSave(editing_form, "action")

self.assertEquals(
self.site_properties.getProperty('visible_ids'), True)


def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

3 comments on commit 91d0c2f

@davisagli
Copy link
Member

Choose a reason for hiding this comment

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

Go Timo!

I'm not sure we should get rid of the old adapters though. The form is much more readable without them, so that's great. But sad to say, I have code in projects that do things like:

editing_settings = getAdapter(site, IEditingSchema)
editing_settings.enable_link_integrity_checks = False

because it was the most readable way to manage that setting.

We could certainly choose to deprecate them though.

@tisto
Copy link
Member

@tisto tisto commented on 91d0c2f Mar 15, 2012

Choose a reason for hiding this comment

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

Hi David,

I re-added the adapter, so your code will still work:

https://github.com/plone/plone.app.controlpanel/blob/plip10359-z3cform/plone/app/controlpanel/browser/editing.py#L144
https://github.com/plone/plone.app.controlpanel/blob/plip10359-z3cform/plone/app/controlpanel/tests/test_editing.py#L87

Let me know if this would be ok with you. I think we should deprecate this approach, especially if we should choose to move to a plone.app.registry based approach for portal_properties at some point. This is something we can decide during the PLIP process though.

@davisagli
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that looks okay. +1 for deprecating these but keeping them around for the next 2 minor releases.

Please sign in to comment.