[Checkins] SVN: CMF/trunk/CMFDefault/ - replaced document and news
item edit forms by formlib based forms
Yvo Schubbe
y.2007- at wcm-solutions.de
Sun Feb 4 10:31:52 EST 2007
Log message for revision 72362:
- replaced document and news item edit forms by formlib based forms
Changed:
U CMF/trunk/CMFDefault/browser/TODO.txt
U CMF/trunk/CMFDefault/browser/configure.zcml
U CMF/trunk/CMFDefault/browser/document.py
A CMF/trunk/CMFDefault/browser/document.txt
U CMF/trunk/CMFDefault/browser/newsitem.py
D CMF/trunk/CMFDefault/browser/templates/document_edit.pt
D CMF/trunk/CMFDefault/browser/templates/newsitem_edit.pt
U CMF/trunk/CMFDefault/browser/tests.py
U CMF/trunk/CMFDefault/formlib/editform.pt
U CMF/trunk/CMFDefault/formlib/vocabulary.py
U CMF/trunk/CMFDefault/formlib/widgets.py
U CMF/trunk/CMFDefault/locales/cmf_default.pot
U CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css
-=-
Modified: CMF/trunk/CMFDefault/browser/TODO.txt
===================================================================
--- CMF/trunk/CMFDefault/browser/TODO.txt 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/TODO.txt 2007-02-04 15:31:51 UTC (rev 72362)
@@ -55,18 +55,18 @@
[x] IMutableDocument @@edit.html:
document_edit_form.py -> DocumentEditView
- document_edit_template.pt -> templates/document_edit.pt
- validateHTML.py -> DocumentEditView.validateHTML
- validateTextFile.py -> DocumentEditView.validateTextFile
- document_edit_control.py -> DocumentEditView.edit_control
+ document_edit_template.pt -> formlib based
+ validateHTML.py -> formlib based
+ validateTextFile.py -> formlib based
+ document_edit_control.py -> formlib based
[x] IMutableNewsItem @@edit.html:
newsitem_edit_form.py -> NewsItemEditView
- newsitem_edit_template.pt -> templates/newsitem_edit.pt
- validateHTML.py -> DocumentEditView.validateHTML
- validateTextFile.py -> DocumentEditView.validateTextFile
- newsitem_edit_control.py -> NewsItemEditView.edit_control
+ newsitem_edit_template.pt -> formlib based
+ validateHTML.py -> formlib based
+ validateTextFile.py -> formlib based
+ newsitem_edit_control.py -> formlib based
[x] ILink @@view.html:
Modified: CMF/trunk/CMFDefault/browser/configure.zcml
===================================================================
--- CMF/trunk/CMFDefault/browser/configure.zcml 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/configure.zcml 2007-02-04 15:31:51 UTC (rev 72362)
@@ -40,6 +40,13 @@
permission="cmf.ModifyPortalContent"
/>
+ <adapter factory=".document.DocumentSchemaAdapter"/>
+
+ <utility
+ component=".document.TextFormatVocabularyFactory"
+ name="cmf.AvailableTextFormats"
+ />
+
<browser:page
for="..interfaces.IDocument"
layer="..interfaces.ICMFDefaultSkin"
@@ -54,16 +61,16 @@
layer="..interfaces.ICMFDefaultSkin"
name="edit.html"
class=".document.DocumentEditView"
- template="templates/document_edit.pt"
permission="cmf.ModifyPortalContent"
/>
+ <adapter factory=".newsitem.NewsItemSchemaAdapter"/>
+
<browser:page
for="..interfaces.IMutableNewsItem"
layer="..interfaces.ICMFDefaultSkin"
name="edit.html"
class=".newsitem.NewsItemEditView"
- template="templates/newsitem_edit.pt"
permission="cmf.ModifyPortalContent"
/>
Modified: CMF/trunk/CMFDefault/browser/document.py
===================================================================
--- CMF/trunk/CMFDefault/browser/document.py 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/document.py 2007-02-04 15:31:51 UTC (rev 72362)
@@ -15,97 +15,129 @@
$Id$
"""
-from Products.CMFDefault.exceptions import EditingConflict
-from Products.CMFDefault.exceptions import IllegalHTML
-from Products.CMFDefault.exceptions import ResourceLockedError
+from zope.component import adapts
+from zope.formlib import form
+from zope.interface import implements
+from zope.interface import Interface
+from zope.schema import ASCIILine
+from zope.schema import Bytes
+from zope.schema import Choice
+from zope.schema import Text
+from zope.schema import TextLine
+
+from Products.CMFDefault.formlib.form import ContentEditFormBase
+from Products.CMFDefault.formlib.schema import ProxyFieldProperty
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFDefault.formlib.vocabulary import StaticVocabulary
+from Products.CMFDefault.formlib.widgets import ChoiceRadioWidget
+from Products.CMFDefault.formlib.widgets import TextInputWidget
+from Products.CMFDefault.interfaces import IMutableDocument
from Products.CMFDefault.utils import Message as _
-from Products.CMFDefault.utils import scrubHTML
from utils import decode
-from utils import FormViewBase
from utils import memoize
from utils import ViewBase
+available_text_formats = (
+ (u'structured-text', 'structured-text', _(u'structured-text')),
+ (u'plain', 'plain', _(u'plain text')),
+ (u'html', 'html', _(u'html')))
-class DocumentView(ViewBase):
+TextFormatVocabularyFactory = StaticVocabulary(available_text_formats)
- """View for IDocument.
+
+class IDocumentSchema(Interface):
+
+ """Schema for document views.
"""
- # interface
+ safety_belt = ASCIILine()
- @memoize
- @decode
- def text(self):
- return self.context.CookedBody()
+ title = TextLine(
+ title=_(u'Title'),
+ readonly=True)
+ description = Text(
+ title=_(u'Description'),
+ readonly=True)
-class DocumentEditView(FormViewBase):
+ text_format = Choice(
+ title=_(u'Format'),
+ vocabulary='cmf.AvailableTextFormats')
- """Edit view for IMutableDocument.
+ upload = Bytes(
+ title=_(u'Upload'),
+ required=False)
+
+ text = Text(
+ title=_(u'Body'),
+ required=False,
+ missing_value=u'')
+
+
+class DocumentSchemaAdapter(SchemaAdapterBase):
+
+ """Adapter for IMutableDocument.
"""
- _BUTTONS = ({'id': 'change',
- 'title': _(u'Change'),
- 'transform': ('validateTextFile', 'validateHTML',
- 'edit_control'),
- 'redirect': ('portal_types', 'object/edit')},
- {'id': 'change_and_view',
- 'title': _(u'Change and View'),
- 'transform': ('validateTextFile', 'validateHTML',
- 'edit_control'),
- 'redirect': ('portal_types', 'object/view')})
+ adapts(IMutableDocument)
+ implements(IDocumentSchema)
- #helpers
+ safety_belt = ProxyFieldProperty(IDocumentSchema['safety_belt'],
+ 'SafetyBelt')
+ title = ProxyFieldProperty(IDocumentSchema['title'], 'Title')
+ description = ProxyFieldProperty(IDocumentSchema['description'],
+ 'Description')
+ text_format = ProxyFieldProperty(IDocumentSchema['text_format'])
+ upload = None
+ text = ProxyFieldProperty(IDocumentSchema['text'],
+ 'EditableBody', '_edit')
- @memoize
- def _getHiddenVars(self):
- belt = self.request.form.get('SafetyBelt', self.context.SafetyBelt())
- return {'SafetyBelt': belt}
+class DocumentView(ViewBase):
+
+ """View for IDocument.
+ """
+
# interface
@memoize
- def text_format(self):
- return self.request.form.get('text_format', self.context.text_format)
-
- @memoize
@decode
def text(self):
- return self.request.form.get('text', self.context.EditableBody())
+ return self.context.CookedBody()
- # validators
- def validateHTML(self, text, description='', **kw):
- try:
- self.request.form['description'] = scrubHTML(description)
- self.request.form['text'] = scrubHTML(text)
- return True
- except IllegalHTML, errmsg:
- return False, errmsg
+class DocumentEditView(ContentEditFormBase):
- def validateTextFile(self, file='', **kw):
- try:
- upload = file.read()
- except AttributeError:
- return True
- else:
- if upload:
- self.request.form['text'] = upload
- return True
- else:
- return True
+ """Edit view for IMutableDocument.
+ """
- # controllers
+ form_fields = form.FormFields(IDocumentSchema)
+ form_fields['text_format'].custom_widget = ChoiceRadioWidget
+ form_fields['text'].custom_widget = TextInputWidget
- def edit_control(self, text_format, text, SafetyBelt='', **kw):
- context = self.context
- if text_format != context.text_format or \
- text != context.EditableBody():
- try:
- context.edit(text_format, text, safety_belt=SafetyBelt)
- return True, _(u'Document changed.')
- except (ResourceLockedError, EditingConflict), errmsg:
- return False, errmsg
- else:
- return False, _(u'Nothing to change.')
+ def setUpWidgets(self, ignore_request=False):
+ super(DocumentEditView,
+ self).setUpWidgets(ignore_request=ignore_request)
+ self.widgets['safety_belt'].hide = True
+ self.widgets['description'].height = 3
+ self.widgets['text_format'].orientation = 'horizontal'
+ self.widgets['upload'].displayWidth = 60
+ self.widgets['text'].height = 20
+
+ def _handle_success(self, action, data):
+ body = data.get('upload')
+ if body:
+ data['text'] = body.decode(self._getDefaultCharset())
+ super(DocumentEditView, self)._handle_success(action, data)
+
+ def handle_validate(self, action, data):
+ errors = super(DocumentEditView, self).handle_validate(action, data)
+ if errors:
+ return errors
+ safety_belt = self.request.form['form.safety_belt']
+ if not self.context._safety_belt_update(safety_belt):
+ return (_(u'Intervening changes from elsewhere detected. Please '
+ u'refetch the document and reapply your changes.'),)
+ self.request.form['form.safety_belt'] = self.context.SafetyBelt()
+ return None
Added: CMF/trunk/CMFDefault/browser/document.txt
===================================================================
--- CMF/trunk/CMFDefault/browser/document.txt 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/document.txt 2007-02-04 15:31:51 UTC (rev 72362)
@@ -0,0 +1,68 @@
+Document Views
+--------------
+
+Set up Document and user.
+
+ >>> from Products.CMFDefault.Document import Document
+ >>> id = app.site._setObject('myDocument', Document('myDocument'))
+
+ >>> uf = app.site.acl_users
+ >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+ >>> from Products.Five.testbrowser import Browser
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+ >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the edit form with invalid input.
+
+ >>> browser.open('http://localhost/site/myDocument/@@edit.html')
+ >>> browser.getControl('[[cmf_default][Body]]').value = '<script>'
+ >>> browser.getControl('[[cmf_default][Change]]').click()
+ >>> '[[zope][There were errors]]' in browser.contents
+ True
+ >>> '[[cmf_default][Dynamic tag \'script\' not ' in browser.contents
+ True
+
+Use the edit form with valid input.
+
+ >>> browser.getControl('[[cmf_default][Body]]').value = 'spam'
+ >>> browser.getControl('[[cmf_default][Change]]').click()
+ >>> '[[zope][There were errors]]' in browser.contents
+ False
+
+Look at the result.
+
+ >>> browser.open('http://localhost/site/myDocument/@@view.html')
+ >>> 'spam' in browser.contents
+ True
+
+Changes can't be saved if the safety belt is invalid.
+
+ >>> browser.open('http://localhost/site/myDocument/@@edit.html')
+
+ >>> app.site.myDocument._safety_belt = '1'
+
+ >>> browser.getControl('[[cmf_default][Body]]').value = 'spam and eggs'
+ >>> browser.getControl('[[cmf_default][Change]]').click()
+ >>> '[[zope][There were errors]]' in browser.contents
+ True
+ >>> '[[cmf_default][Intervening changes from ' in browser.contents
+ True
+
+Changes can't be saved if the document is locked.
+
+ >>> browser.open('http://localhost/site/myDocument/@@edit.html')
+
+ >>> from webdav.LockItem import LockItem
+ >>> lock = LockItem(uf.getUser('mgr').__of__(uf))
+ >>> app.site.myDocument.wl_setLock(lock.getLockToken(), lock)
+
+ >>> browser.getControl('[[cmf_default][Body]]').value = 'spam and eggs'
+ >>> browser.getControl('[[cmf_default][Change]]').click()
+ >>> '[[zope][There were errors]]' in browser.contents
+ True
+ >>> '[[cmf_default][This resource is locked ' in browser.contents
+ True
Property changes on: CMF/trunk/CMFDefault/browser/document.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: CMF/trunk/CMFDefault/browser/newsitem.py
===================================================================
--- CMF/trunk/CMFDefault/browser/newsitem.py 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/newsitem.py 2007-02-04 15:31:51 UTC (rev 72362)
@@ -15,39 +15,76 @@
$Id$
"""
-from Products.CMFDefault.exceptions import ResourceLockedError
+from zope.component import adapts
+from zope.formlib import form
+from zope.interface import implements
+from zope.interface import Interface
+from zope.schema import Choice
+from zope.schema import Text
+from zope.schema import TextLine
+
+from Products.CMFDefault.formlib.form import ContentEditFormBase
+from Products.CMFDefault.formlib.schema import ProxyFieldProperty
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFDefault.formlib.widgets import ChoiceRadioWidget
+from Products.CMFDefault.formlib.widgets import TextInputWidget
+from Products.CMFDefault.interfaces import IMutableNewsItem
from Products.CMFDefault.utils import Message as _
-from document import DocumentEditView
-from utils import decode
-from utils import memoize
+class INewsItemSchema(Interface):
-class NewsItemEditView(DocumentEditView):
+ """Schema for news item views.
+ """
- """Edit view for INewsItem.
+ title = TextLine(
+ title=_(u'Title'),
+ readonly=True)
+
+ text_format = Choice(
+ title=_(u'Format'),
+ vocabulary='cmf.AvailableTextFormats')
+
+ description = Text(
+ title=_(u'Lead-in'),
+ required=False,
+ missing_value=u'')
+
+ text = Text(
+ title=_(u'Body'),
+ required=False,
+ missing_value=u'')
+
+
+class NewsItemSchemaAdapter(SchemaAdapterBase):
+
+ """Adapter for IMutableNewsItem.
"""
- # interface
+ adapts(IMutableNewsItem)
+ implements(INewsItemSchema)
- @memoize
- @decode
- def description(self):
- return self.request.form.get('description',
- self.context.Description())
+ title = ProxyFieldProperty(INewsItemSchema['title'], 'Title')
+ text_format = ProxyFieldProperty(INewsItemSchema['text_format'])
+ description = ProxyFieldProperty(INewsItemSchema['description'],
+ 'Description', 'setDescription')
+ text = ProxyFieldProperty(INewsItemSchema['text'],
+ 'EditableBody', '_edit')
- # controllers
- def edit_control(self, text_format, text, description='', **kw):
- context = self.context
- if description != context.Description() or \
- text_format != context.text_format or \
- text != context.EditableBody():
- try:
- context.edit(text=text, description=description,
- text_format=text_format)
- return True, _(u'News Item changed.')
- except ResourceLockedError, errmsg:
- return False, errmsg
- else:
- return False, _(u'Nothing to change.')
+class NewsItemEditView(ContentEditFormBase):
+
+ """Edit view for INewsItem.
+ """
+
+ form_fields = form.FormFields(INewsItemSchema)
+ form_fields['text_format'].custom_widget = ChoiceRadioWidget
+ form_fields['description'].custom_widget = TextInputWidget
+ form_fields['text'].custom_widget = TextInputWidget
+
+ def setUpWidgets(self, ignore_request=False):
+ super(NewsItemEditView,
+ self).setUpWidgets(ignore_request=ignore_request)
+ self.widgets['text_format'].orientation = 'horizontal'
+ self.widgets['description'].height = 8
+ self.widgets['text'].height = 16
Deleted: CMF/trunk/CMFDefault/browser/templates/document_edit.pt
===================================================================
--- CMF/trunk/CMFDefault/browser/templates/document_edit.pt 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/templates/document_edit.pt 2007-02-04 15:31:51 UTC (rev 72362)
@@ -1,58 +0,0 @@
-<html metal:use-macro="context/@@standard_macros/page">
-<body>
-
-<metal:slot metal:fill-slot="body" i18n:domain="cmf_default">
-<h1 i18n:translate="">Edit: <tal:span
- tal:content="view/title" i18n:name="obj_title">Title</tal:span></h1>
-
-<form action="document_edit_form" method="post" enctype="multipart/form-data"
- tal:attributes="action view/form_action"
-><metal:macro metal:use-macro="context/@@form_widget/hidden_vars" />
-<table class="FormLayout">
- <tr>
- <th i18n:translate="">Title</th>
- <td tal:content="view/title">Title</td>
- </tr>
- <tr>
- <th i18n:translate="">Description</th>
- <td tal:content="view/description">Description</td>
- </tr>
- <tr>
- <th i18n:translate="">Format</th>
- <td>
- <input type="radio" name="text_format" value="structured-text" id="cb_stx"
- tal:attributes="checked python: view.text_format()=='structured-text'" />
- <label for="cb_stx" i18n:translate="">structured-text</label>
- <input type="radio" name="text_format" value="plain" id="cb_plain"
- tal:attributes="checked python: view.text_format()=='plain'" />
- <label for="cb_plain" i18n:translate="">plain text</label>
- <input type="radio" name="text_format" value="html" id="cb_html"
- tal:attributes="checked python: view.text_format()=='html'" />
- <label for="cb_html" i18n:translate="">html</label>
- </td>
- </tr>
- <tr>
- <th i18n:translate="">Upload</th>
- <td>
- <input type="file" name="file" size="40" />
- </td>
- </tr>
- <tr>
- <th i18n:translate="">Edit</th>
- <td>
- <textarea name="text:text" rows="20" cols="80" wrap="soft"
- tal:content="view/text"></textarea>
- </td>
- </tr>
- <tr>
- <td> </td>
- <td>
- <metal:macro metal:use-macro="context/@@form_widget/buttons" />
- </td>
- </tr>
-</table>
-</form>
-</metal:slot>
-
-</body>
-</html>
Deleted: CMF/trunk/CMFDefault/browser/templates/newsitem_edit.pt
===================================================================
--- CMF/trunk/CMFDefault/browser/templates/newsitem_edit.pt 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/templates/newsitem_edit.pt 2007-02-04 15:31:51 UTC (rev 72362)
@@ -1,54 +0,0 @@
-<html metal:use-macro="context/@@standard_macros/page">
-<body>
-
-<metal:slot metal:fill-slot="body" i18n:domain="cmf_default">
-<h1 i18n:translate="">Edit: <tal:span
- tal:content="view/title" i18n:name="obj_title">Title</tal:span></h1>
-
-<form action="newsitem_edit_form" method="post"
- tal:attributes="action view/form_action">
-<table class="FormLayout">
- <tr>
- <th i18n:translate="">Title</th>
- <td tal:content="view/title">Title</td>
- </tr>
- <tr>
- <th i18n:translate="">Format</th>
- <td>
- <input type="radio" name="text_format" value="structured-text" id="cb_stx"
- tal:attributes="checked python: view.text_format()=='structured-text'" />
- <label for="cb_stx" i18n:translate="">structured-text</label>
- <input type="radio" name="text_format" value="plain" id="cb_plain"
- tal:attributes="checked python: view.text_format()=='plain'" />
- <label for="cb_plain" i18n:translate="">plain text</label>
- <input type="radio" name="text_format" value="html" id="cb_html"
- tal:attributes="checked python: view.text_format()=='html'" />
- <label for="cb_html" i18n:translate="">html</label>
- </td>
- </tr>
- <tr>
- <th i18n:translate="">Lead-in</th>
- <td>
- <textarea name="description:text" rows="8" cols="80" wrap="soft"
- tal:content="view/description"></textarea>
- </td>
- </tr>
- <tr>
- <th i18n:translate="">Body</th>
- <td>
- <textarea name="text:text" rows="16" cols="80" wrap="soft"
- tal:content="view/text"></textarea>
- </td>
- </tr>
- <tr>
- <td> </td>
- <td>
- <metal:macro metal:use-macro="context/@@form_widget/buttons" />
- </td>
- </tr>
-</table>
-</form>
-</metal:slot>
-
-</body>
-</html>
Modified: CMF/trunk/CMFDefault/browser/tests.py
===================================================================
--- CMF/trunk/CMFDefault/browser/tests.py 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/browser/tests.py 2007-02-04 15:31:51 UTC (rev 72362)
@@ -29,6 +29,9 @@
s = ZopeTestCase.FunctionalDocFileSuite('metadata.txt')
s.layer = FunctionalLayer
suite.addTest(s)
+ s = ZopeTestCase.FunctionalDocFileSuite('document.txt')
+ s.layer = FunctionalLayer
+ suite.addTest(s)
return suite
if __name__ == '__main__':
Modified: CMF/trunk/CMFDefault/formlib/editform.pt
===================================================================
--- CMF/trunk/CMFDefault/formlib/editform.pt 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/formlib/editform.pt 2007-02-04 15:31:51 UTC (rev 72362)
@@ -13,7 +13,7 @@
tal:attributes="action request/ACTUAL_URL">
<div class="widgets">
<tal:loop tal:repeat="widget view/widgets"
-><div class="widget"
+><div class="widget" tal:condition="not: widget/hide|nothing"
tal:define="split widget/split|nothing; hint widget/hint|nothing"
tal:attributes="class python: split and 'widget split' or 'widget'">
<label tal:attributes="for widget/name; title python: hint or None"
@@ -23,7 +23,9 @@
<div class="data"><tal:span tal:replace="structure widget" /></div
><tal:case tal:condition="widget/error"
tal:replace="structure widget/error" /></div>
- </div></tal:loop>
+ </div
+><tal:span tal:condition="widget/hide|nothing"
+ tal:replace="structure widget/hidden" /></tal:loop>
</div>
<div class="clear"></div>
Modified: CMF/trunk/CMFDefault/formlib/vocabulary.py
===================================================================
--- CMF/trunk/CMFDefault/formlib/vocabulary.py 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/formlib/vocabulary.py 2007-02-04 15:31:51 UTC (rev 72362)
@@ -15,6 +15,8 @@
$Id$
"""
+from zope.interface import implements
+from zope.schema.interfaces import IVocabularyFactory
from zope.schema.vocabulary import SimpleVocabulary
@@ -28,3 +30,17 @@
return cls(terms, *interfaces)
fromTitleItems = classmethod(fromTitleItems)
+
+
+class StaticVocabulary(object):
+
+ """Vocabulary factory for static items.
+ """
+
+ implements(IVocabularyFactory)
+
+ def __init__(self, items):
+ self._vocabulary = SimpleVocabulary.fromTitleItems(items)
+
+ def __call__(self, context):
+ return self._vocabulary
Modified: CMF/trunk/CMFDefault/formlib/widgets.py
===================================================================
--- CMF/trunk/CMFDefault/formlib/widgets.py 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/formlib/widgets.py 2007-02-04 15:31:51 UTC (rev 72362)
@@ -18,10 +18,12 @@
from zope.app.form import InputWidget
from zope.app.form.browser import BrowserWidget
from zope.app.form.browser import MultiSelectSetWidget
+from zope.app.form.browser import RadioWidget
from zope.app.form.browser import TextWidget
from zope.app.form.browser import TextAreaWidget
from zope.app.form.interfaces import ConversionError
from zope.app.form.interfaces import IInputWidget
+from zope.app.form.interfaces import WidgetInputError
from zope.component import adapts
from zope.interface import implementsOnly
from zope.publisher.interfaces.browser import IBrowserRequest
@@ -32,11 +34,19 @@
from zope.schema.interfaces import ITextLine
from Products.CMFCore.utils import getToolByName
-from Products.CMFDefault.formlib.schema import IEmailLine
-from Products.CMFDefault.formlib.vocabulary import SimpleVocabulary
+from Products.CMFDefault.exceptions import IllegalHTML
+from Products.CMFDefault.utils import scrubHTML
from Products.CMFDefault.utils import Message as _
+from schema import IEmailLine
+from vocabulary import SimpleVocabulary
+# generic widgets
+
+def ChoiceRadioWidget(field, request):
+ return RadioWidget(field, field.vocabulary, request)
+
+
class EmailInputWidget(TextWidget):
implementsOnly(IInputWidget)
@@ -52,6 +62,20 @@
raise ConversionError(_(u'Invalid email address.'), err)
+class TextInputWidget(TextAreaWidget):
+
+ def getInputValue(self):
+ value = super(TextInputWidget, self).getInputValue()
+ if value:
+ try:
+ value = scrubHTML(value)
+ except IllegalHTML, err:
+ self._error = WidgetInputError(self.context.__name__,
+ self.label, err.args[0])
+ raise self._error
+ return value
+
+
class TupleTextAreaWidget(TextAreaWidget):
implementsOnly(IInputWidget)
@@ -81,6 +105,8 @@
return TupleTextAreaWidget(field, field.value_type, request)
+# special widgets
+
class SubjectInputWidget(InputWidget, BrowserWidget):
implementsOnly(IInputWidget)
Modified: CMF/trunk/CMFDefault/locales/cmf_default.pot
===================================================================
--- CMF/trunk/CMFDefault/locales/cmf_default.pot 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/locales/cmf_default.pot 2007-02-04 15:31:51 UTC (rev 72362)
@@ -19,32 +19,37 @@
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+#: CMFCore/PortalContent.py:79
+#: CMFDefault/formlib/form.py:127
+msgid "This resource is locked via webDAV."
+msgstr ""
+
#: CMFCore/RegistrationTool.py:144
#: CMFDefault/RegistrationTool.py:94
msgid "The login name you selected is already in use or is not valid. Please choose another."
msgstr ""
-#: CMFCore/WorkflowTool.py:225
-#: CMFCore/WorkflowTool.py:251
+#: CMFCore/WorkflowTool.py:228
+#: CMFCore/WorkflowTool.py:254
msgid "No workflows found."
msgstr ""
-#: CMFCore/WorkflowTool.py:232
+#: CMFCore/WorkflowTool.py:235
#. Default: ""
msgid "No workflow provides the '${action_id}' action."
msgstr ""
-#: CMFCore/WorkflowTool.py:239
-#: CMFCore/WorkflowTool.py:271
+#: CMFCore/WorkflowTool.py:242
+#: CMFCore/WorkflowTool.py:274
msgid "Requested workflow definition not found."
msgstr ""
-#: CMFCore/WorkflowTool.py:261
+#: CMFCore/WorkflowTool.py:264
#. Default: ""
msgid "No workflow provides '${name}' information."
msgstr ""
-#: CMFCore/WorkflowTool.py:276
+#: CMFCore/WorkflowTool.py:279
#. Default: ""
msgid "Could not get info: ${name}"
msgstr ""
@@ -89,70 +94,36 @@
msgid "You must enter an email address."
msgstr ""
-#: CMFDefault/browser/document.py:107
-#: CMFDefault/skins/zpt_content/document_edit_control.py:10
-msgid "Document changed."
+#: CMFDefault/browser/document.py:140
+msgid "Intervening changes from elsewhere detected. Please refetch the document and reapply your changes."
msgstr ""
-#: CMFDefault/browser/document.py:111
-#: CMFDefault/browser/folder.py:359
-#: CMFDefault/browser/folder.py:374
-#: CMFDefault/browser/folder.py:389
-#: CMFDefault/browser/folder.py:404
-#: CMFDefault/browser/newsitem.py:53
-#: CMFDefault/formlib/form.py:144
-#: CMFDefault/skins/zpt_content/document_edit_control.py:14
-#: CMFDefault/skins/zpt_content/folder_edit_control.py:9
-#: CMFDefault/skins/zpt_content/link_edit_control.py:13
-#: CMFDefault/skins/zpt_content/newsitem_edit_control.py:15
-#: CMFDefault/skins/zpt_control/folder_bottom_control.py:13
-#: CMFDefault/skins/zpt_control/folder_down_control.py:13
-#: CMFDefault/skins/zpt_control/folder_rename_control.py:17
-#: CMFDefault/skins/zpt_control/folder_top_control.py:13
-#: CMFDefault/skins/zpt_control/folder_up_control.py:13
-#: CMFTopic/skins/zpt_topic/topic_edit_control.py:11
-msgid "Nothing to change."
+#: CMFDefault/browser/document.py:42
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:28
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:23
+msgid "structured-text"
msgstr ""
-#: CMFDefault/browser/document.py:49
-#: CMFDefault/browser/metadata.py:223
-#: CMFDefault/formlib/form.py:100
-#: CMFDefault/skins/zpt_content/document_edit_form.py:34
-#: CMFDefault/skins/zpt_content/file_edit_form.py:25
-#: CMFDefault/skins/zpt_content/folder_edit_form.py:24
-#: CMFDefault/skins/zpt_content/image_edit_form.py:25
-#: CMFDefault/skins/zpt_content/link_edit_form.py:24
-#: CMFDefault/skins/zpt_content/metadata_edit_form.py:49
-#: CMFDefault/skins/zpt_content/newsitem_edit_form.py:28
-#: CMFDefault/skins/zpt_generic/password_form.py:37
-#: CMFDefault/skins/zpt_generic/reconfig_form.py:22
-#: CMFTopic/skins/zpt_topic/topic_edit_form.py:26
-#: CMFDefault/skins/zpt_generic/personalize_form.pt:83
-msgid "Change"
+#: CMFDefault/browser/document.py:43
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:31
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:26
+msgid "plain text"
msgstr ""
-#: CMFDefault/browser/document.py:54
-#: CMFDefault/browser/metadata.py:235
-#: CMFDefault/formlib/form.py:106
-#: CMFDefault/skins/zpt_content/document_edit_form.py:35
-#: CMFDefault/skins/zpt_content/file_edit_form.py:26
-#: CMFDefault/skins/zpt_content/folder_edit_form.py:25
-#: CMFDefault/skins/zpt_content/image_edit_form.py:26
-#: CMFDefault/skins/zpt_content/link_edit_form.py:25
-#: CMFDefault/skins/zpt_content/metadata_edit_form.py:51
-#: CMFDefault/skins/zpt_content/newsitem_edit_form.py:29
-#: CMFTopic/skins/zpt_topic/topic_edit_form.py:27
-msgid "Change and View"
+#: CMFDefault/browser/document.py:44
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:34
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:29
+msgid "html"
msgstr ""
+#: CMFDefault/browser/document.py:57
#: CMFDefault/browser/favorite.py:39
#: CMFDefault/browser/favorite.py:40
#: CMFDefault/browser/link.py:42
#: CMFDefault/browser/link.py:43
#: CMFDefault/browser/metadata.py:54
#: CMFDefault/browser/metadata.py:79
-#: CMFDefault/browser/templates/document_edit.pt:13
-#: CMFDefault/browser/templates/newsitem_edit.pt:12
+#: CMFDefault/browser/newsitem.py:41
#: CMFDefault/skins/zpt_content/document_edit_template.pt:16
#: CMFDefault/skins/zpt_content/file_edit_template.pt:15
#: CMFDefault/skins/zpt_content/folder_edit_template.pt:15
@@ -168,6 +139,41 @@
msgid "Title"
msgstr ""
+#: CMFDefault/browser/document.py:61
+#: CMFDefault/browser/metadata.py:59
+#: CMFDefault/browser/metadata.py:84
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:20
+#: CMFDefault/skins/zpt_content/file_edit_template.pt:19
+#: CMFDefault/skins/zpt_content/folder_edit_template.pt:22
+#: CMFDefault/skins/zpt_content/image_edit_template.pt:19
+#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:44
+#: CMFDefault/skins/zpt_generic/metadata_help.pt:52
+#: CMFDefault/skins/zpt_generic/search_form_template.pt:67
+#: CMFTopic/skins/zpt_topic/topic_edit_template.pt:22
+msgid "Description"
+msgstr ""
+
+#: CMFDefault/browser/document.py:65
+#: CMFDefault/browser/metadata.py:119
+#: CMFDefault/browser/newsitem.py:45
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:24
+#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:90
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:19
+#: CMFDefault/skins/zpt_generic/metadata_help.pt:124
+msgid "Format"
+msgstr ""
+
+#: CMFDefault/browser/document.py:69
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:38
+msgid "Upload"
+msgstr ""
+
+#: CMFDefault/browser/document.py:73
+#: CMFDefault/browser/newsitem.py:54
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:40
+msgid "Body"
+msgstr ""
+
#: CMFDefault/browser/favorite.py:44
#: CMFDefault/browser/link.py:47
#: CMFDefault/skins/zpt_content/link_edit_template.pt:19
@@ -286,6 +292,24 @@
msgid "Items moved up."
msgstr ""
+#: CMFDefault/browser/folder.py:359
+#: CMFDefault/browser/folder.py:374
+#: CMFDefault/browser/folder.py:389
+#: CMFDefault/browser/folder.py:404
+#: CMFDefault/formlib/form.py:144
+#: CMFDefault/skins/zpt_content/document_edit_control.py:14
+#: CMFDefault/skins/zpt_content/folder_edit_control.py:9
+#: CMFDefault/skins/zpt_content/link_edit_control.py:13
+#: CMFDefault/skins/zpt_content/newsitem_edit_control.py:15
+#: CMFDefault/skins/zpt_control/folder_bottom_control.py:13
+#: CMFDefault/skins/zpt_control/folder_down_control.py:13
+#: CMFDefault/skins/zpt_control/folder_rename_control.py:17
+#: CMFDefault/skins/zpt_control/folder_top_control.py:13
+#: CMFDefault/skins/zpt_control/folder_up_control.py:13
+#: CMFTopic/skins/zpt_topic/topic_edit_control.py:11
+msgid "Nothing to change."
+msgstr ""
+
#: CMFDefault/browser/folder.py:361
#: CMFDefault/browser/folder.py:376
#: CMFDefault/browser/folder.py:391
@@ -388,16 +412,6 @@
msgid "Expiration Date"
msgstr ""
-#: CMFDefault/browser/metadata.py:119
-#: CMFDefault/browser/templates/document_edit.pt:21
-#: CMFDefault/browser/templates/newsitem_edit.pt:16
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:24
-#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:90
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:19
-#: CMFDefault/skins/zpt_generic/metadata_help.pt:124
-msgid "Format"
-msgstr ""
-
#: CMFDefault/browser/metadata.py:124
#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:97
#: CMFDefault/skins/zpt_generic/metadata_help.pt:149
@@ -415,11 +429,40 @@
msgid "Properties"
msgstr ""
+#: CMFDefault/browser/metadata.py:223
+#: CMFDefault/formlib/form.py:100
+#: CMFDefault/skins/zpt_content/document_edit_form.py:34
+#: CMFDefault/skins/zpt_content/file_edit_form.py:25
+#: CMFDefault/skins/zpt_content/folder_edit_form.py:24
+#: CMFDefault/skins/zpt_content/image_edit_form.py:25
+#: CMFDefault/skins/zpt_content/link_edit_form.py:24
+#: CMFDefault/skins/zpt_content/metadata_edit_form.py:49
+#: CMFDefault/skins/zpt_content/newsitem_edit_form.py:28
+#: CMFDefault/skins/zpt_generic/password_form.py:37
+#: CMFDefault/skins/zpt_generic/reconfig_form.py:22
+#: CMFTopic/skins/zpt_topic/topic_edit_form.py:26
+#: CMFDefault/skins/zpt_generic/personalize_form.pt:83
+msgid "Change"
+msgstr ""
+
#: CMFDefault/browser/metadata.py:229
#: CMFDefault/skins/zpt_content/metadata_edit_form.py:50
msgid "Change and Edit"
msgstr ""
+#: CMFDefault/browser/metadata.py:235
+#: CMFDefault/formlib/form.py:106
+#: CMFDefault/skins/zpt_content/document_edit_form.py:35
+#: CMFDefault/skins/zpt_content/file_edit_form.py:26
+#: CMFDefault/skins/zpt_content/folder_edit_form.py:25
+#: CMFDefault/skins/zpt_content/image_edit_form.py:26
+#: CMFDefault/skins/zpt_content/link_edit_form.py:25
+#: CMFDefault/skins/zpt_content/metadata_edit_form.py:51
+#: CMFDefault/skins/zpt_content/newsitem_edit_form.py:29
+#: CMFTopic/skins/zpt_topic/topic_edit_form.py:27
+msgid "Change and View"
+msgstr ""
+
#: CMFDefault/browser/metadata.py:251
#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:18
msgid "Default"
@@ -435,20 +478,6 @@
msgid "On"
msgstr ""
-#: CMFDefault/browser/metadata.py:59
-#: CMFDefault/browser/metadata.py:84
-#: CMFDefault/browser/templates/document_edit.pt:17
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:20
-#: CMFDefault/skins/zpt_content/file_edit_template.pt:19
-#: CMFDefault/skins/zpt_content/folder_edit_template.pt:22
-#: CMFDefault/skins/zpt_content/image_edit_template.pt:19
-#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:44
-#: CMFDefault/skins/zpt_generic/metadata_help.pt:52
-#: CMFDefault/skins/zpt_generic/search_form_template.pt:67
-#: CMFTopic/skins/zpt_topic/topic_edit_template.pt:22
-msgid "Description"
-msgstr ""
-
#: CMFDefault/browser/metadata.py:70
#: CMFDefault/skins/zpt_content/metadata_edit_template.pt:15
msgid "Enable Discussion?"
@@ -473,8 +502,8 @@
msgstr ""
#: CMFDefault/browser/newsitem.py:49
-#: CMFDefault/skins/zpt_content/newsitem_edit_control.py:11
-msgid "News Item changed."
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:33
+msgid "Lead-in"
msgstr ""
#: CMFDefault/browser/templates/batch_widgets.pt:10
@@ -493,44 +522,6 @@
msgid "${DYNAMIC_CONTENT}"
msgstr ""
-#: CMFDefault/browser/templates/document_edit.pt:25
-#: CMFDefault/browser/templates/newsitem_edit.pt:20
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:28
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:23
-msgid "structured-text"
-msgstr ""
-
-#: CMFDefault/browser/templates/document_edit.pt:28
-#: CMFDefault/browser/templates/newsitem_edit.pt:23
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:31
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:26
-msgid "plain text"
-msgstr ""
-
-#: CMFDefault/browser/templates/document_edit.pt:31
-#: CMFDefault/browser/templates/newsitem_edit.pt:26
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:34
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:29
-msgid "html"
-msgstr ""
-
-#: CMFDefault/browser/templates/document_edit.pt:35
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:38
-msgid "Upload"
-msgstr ""
-
-#: CMFDefault/browser/templates/document_edit.pt:5
-#: CMFDefault/browser/templates/newsitem_edit.pt:5
-#: CMFDefault/skins/zpt_content/document_edit_template.pt:5
-#: CMFDefault/skins/zpt_content/file_edit_template.pt:5
-#: CMFDefault/skins/zpt_content/folder_edit_template.pt:5
-#: CMFDefault/skins/zpt_content/image_edit_template.pt:5
-#: CMFDefault/skins/zpt_content/link_edit_template.pt:5
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:5
-#: CMFTopic/skins/zpt_topic/topic_edit_template.pt:5
-msgid "Edit: ${obj_title}"
-msgstr ""
-
#: CMFDefault/browser/templates/folder_contents.pt:11
#: CMFDefault/skins/zpt_generic/folder_contents_template.pt:15
msgid "[Link]"
@@ -581,16 +572,6 @@
msgid "Link: ${link}"
msgstr ""
-#: CMFDefault/browser/templates/newsitem_edit.pt:30
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:33
-msgid "Lead-in"
-msgstr ""
-
-#: CMFDefault/browser/templates/newsitem_edit.pt:37
-#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:40
-msgid "Body"
-msgstr ""
-
#: CMFDefault/browser/utils.py:273
msgid "Previous item"
msgstr ""
@@ -620,7 +601,7 @@
msgstr ""
#: CMFDefault/exceptions.py:68
-#: CMFDefault/formlib/widgets.py:52
+#: CMFDefault/formlib/widgets.py:62
msgid "Invalid email address."
msgstr ""
@@ -629,10 +610,6 @@
msgid "Edit ${obj_type}"
msgstr ""
-#: CMFDefault/formlib/form.py:127
-msgid "This resource is locked via webDAV."
-msgstr ""
-
#: CMFDefault/formlib/form.py:141
#. Default: ""
msgid "${obj_type} changed."
@@ -943,6 +920,20 @@
msgid "Submit ${objectid} for Review."
msgstr ""
+#: CMFDefault/skins/zpt_content/document_edit_control.py:10
+msgid "Document changed."
+msgstr ""
+
+#: CMFDefault/skins/zpt_content/document_edit_template.pt:5
+#: CMFDefault/skins/zpt_content/file_edit_template.pt:5
+#: CMFDefault/skins/zpt_content/folder_edit_template.pt:5
+#: CMFDefault/skins/zpt_content/image_edit_template.pt:5
+#: CMFDefault/skins/zpt_content/link_edit_template.pt:5
+#: CMFDefault/skins/zpt_content/newsitem_edit_template.pt:5
+#: CMFTopic/skins/zpt_topic/topic_edit_template.pt:5
+msgid "Edit: ${obj_title}"
+msgstr ""
+
#: CMFDefault/skins/zpt_content/file_edit_control.py:8
msgid "File changed."
msgstr ""
@@ -997,6 +988,10 @@
msgid "Resource Metadata: ${obj_title}"
msgstr ""
+#: CMFDefault/skins/zpt_content/newsitem_edit_control.py:11
+msgid "News Item changed."
+msgstr ""
+
#: CMFDefault/skins/zpt_content/transition_form.pt:11
msgid "Transition of ${objectid}."
msgstr ""
@@ -1136,7 +1131,6 @@
msgstr ""
#: CMFDefault/skins/zpt_generic/discussion_reply_form.py:41
-#: CMFDefault/browser/templates/document_edit.pt:41
#: CMFDefault/skins/zpt_content/document_edit_template.pt:44
msgid "Edit"
msgstr ""
@@ -2102,16 +2096,16 @@
msgid "Query Parameters:"
msgstr ""
-#: DCWorkflow/DCWorkflow.py:280
+#: DCWorkflow/DCWorkflow.py:281
msgid "Object is in an undefined state."
msgstr ""
-#: DCWorkflow/DCWorkflow.py:285
+#: DCWorkflow/DCWorkflow.py:286
#. Default: ""
msgid "Transition '${action_id}' is not triggered by a user action."
msgstr ""
-#: DCWorkflow/DCWorkflow.py:468
+#: DCWorkflow/DCWorkflow.py:469
#. Default: ""
msgid "Destination state undefined: ${state_id}"
msgstr ""
Modified: CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css
===================================================================
--- CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css 2007-02-04 14:54:50 UTC (rev 72361)
+++ CMF/trunk/CMFDefault/skins/zpt_generic/zpt_stylesheet.css 2007-02-04 15:31:51 UTC (rev 72362)
@@ -448,6 +448,8 @@
.widget label { width: 108px; float: left; padding: 0 4px;
min-height: 17px; height: auto !important; height: 17px;
text-align: right; font-size: 80%; font-weight: bold; }
+.widget .data label { width: auto; float: none;
+ font-size: inherit; font-weight: normal; }
.widget .field { width: 604px; float: left;
font-family: inherit; font-size: inherit; }
.widget.split .field { width: 244px; }
@@ -455,13 +457,16 @@
min-height: 30px; height: auto !important; height: 30px;
background-color: #ffffff; }
.widget.split .data { width: 240px; }
-.widget input.textType, .widget select, .widget textarea {
- width: 596px; margin: 0 -2px; padding: 0 2px;
+.widget input.fileType,
+.widget input.textType,
+.widget select,
+.widget textarea { width: 596px; margin: 0 -2px; padding: 0 2px;
font-family: inherit; font-size: inherit; }
.widget select { padding: 0 }
.widget input.textType {
min-height: 30px; height: auto !important; height: 24px; }
-.widget.split input.textType, .widget.split textarea { width: 236px; }
+.widget.split input.textType,
+.widget.split textarea { width: 236px; }
.widget.split select { width: 244px; }
.widget ul { margin: 0 0 0 10px; padding: 0 0 0 10px;
list-style-type: disc; }
More information about the Checkins
mailing list