use composer.schema for form/dialog handling

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2065 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-09-22 14:38:06 +00:00
parent effa162a32
commit 46a1638edd
4 changed files with 108 additions and 26 deletions

View file

@ -651,7 +651,7 @@ on data provided in this form:
>>> note_tc = concepts['note']
>>> component.provideAdapter(NameChooser)
>>> request = TestRequest(form={'form.title': u'Test Note',
>>> request = TestRequest(form={'title': u'Test Note',
... 'form.type': u'.loops/concepts/note'})
>>> view = NodeView(m112, request)
>>> cont = CreateObject(view, request)
@ -668,7 +668,7 @@ created object:
>>> from loops import util
>>> topicUid = util.getUidForObject(topic)
>>> predicateUid = util.getUidForObject(concepts.getDefaultPredicate())
>>> request = TestRequest(form={'form.title': u'Test Note',
>>> request = TestRequest(form={'title': u'Test Note',
... 'form.type': u'.loops/concepts/note',
... 'form.assignments.selected':
... [':'.join((topicUid, predicateUid))]})
@ -711,19 +711,21 @@ The new technique uses the ``fields`` and ``data`` attributes...
>>> for f in view.fields:
... print f.name, f.fieldType, f.required, f.vocabulary
title textline True None
description textarea False None
data textarea False None
contentType dropdown True <...SimpleVocabulary object...>
linkUrl textline False None
>>> view.data
{'linkUrl': None, 'contentType': u'', 'data': '', 'description': '',
{'linkUrl': None, 'contentType': u'', 'data': '',
'title': u'Test Note'}
The object is changed via a FormController adapter created for
a NodeView.
>>> request = TestRequest(form={'form.title': u'Test Note - changed'})
>>> form = dict(
... title=u'Test Note - changed',
... contentType=u'text/plain',)
>>> request = TestRequest(form=form)
>>> view = NodeView(m112, request)
>>> cont = EditObject(view, request)
>>> cont.update()

View file

@ -45,7 +45,7 @@ from cybertools.composer.schema.browser.common import schema_macros, schema_edit
from cybertools.composer.schema.util import getSchemaFromInterface
from cybertools.typology.interfaces import IType, ITypeManager
from loops.common import adapted
from loops.concept import ResourceRelation
from loops.concept import Concept, ResourceRelation
from loops.interfaces import IConcept, IResourceManager, IDocument
from loops.interfaces import IFile, IExternalFile, INote, ITextDocument
from loops.browser.node import NodeView
@ -107,7 +107,13 @@ class ObjectForm(NodeView):
@Lazy
def fields(self):
return self.schema.fields
fields = self.schema.fields
fields.data.height = 10
ifc = self.typeInterface
if ifc in widgetControllers:
wc = widgetControllers[ifc](self.context, self.request)
wc.modifySchemaFields(fields)
return fields
@Lazy
def data(self):
@ -130,7 +136,7 @@ class ObjectForm(NodeView):
def form_fields(self):
ifc = self.typeInterface
ff = FormFields(ifc)
if self.typeInterface in widgetControllers:
if ifc in widgetControllers:
wc = widgetControllers[ifc](self.context, self.request)
ff = wc.modifyFormFields(ff)
return ff
@ -194,6 +200,9 @@ class WidgetController(object):
self.context = context
self.request = request
def modifySchemaFields(self, fields):
pass
def modifyFormFields(self, formFields):
return formFields
@ -203,6 +212,10 @@ class WidgetController(object):
class NoteWidgetController(WidgetController):
def modifySchemaFields(self, fields):
del fields['description']
fields.data.height = 5
def modifyFormFields(self, formFields):
return formFields.omit('description')
@ -212,6 +225,11 @@ class NoteWidgetController(WidgetController):
class FileWidgetController(WidgetController):
def modifySchemaFields(self, fields):
if self.request.principal.id != 'rootadmin':
del fields['contentType']
def modifyFormFields(self, formFields):
if self.request.principal.id == 'rootadmin':
return formFields
@ -289,7 +307,8 @@ class CreateObjectForm(ObjectForm, Form):
class InnerForm(CreateObjectForm):
@property
def macro(self): return self.template.macros['fields']
#def macro(self): return self.template.macros['fields']
def macro(self): return self.schemaMacros['fields']
# processing form input
@ -302,6 +321,27 @@ class EditObject(FormController):
old = None
selected = None
@Lazy
def schema(self):
return getSchemaFromInterface(self.typeInterface, manager=self)
@Lazy
def fields(self):
return self.schema.fields
@Lazy
def instance(self):
return component.getAdapter(adapted(self.object), IInstance, name='editor')
#return IInstance(adapted(self.object), name='editor')
@Lazy
def typeInterface(self):
return IType(self.object).typeInterface or ITextDocument
@Lazy
def loopsRoot(self):
return self.view.loopsRoot
def update(self):
# create new version if necessary
target = self.view.virtualTargetObject
@ -310,20 +350,56 @@ class EditObject(FormController):
# make sure new version is used by the view
self.view.virtualTargetObject = obj
self.request.annotations['loops.view']['target'] = obj
errors = self.updateFields(obj)
if errors:
self.view.setUp()
for fieldName, message in errors.items():
self.view.widgets[fieldName].error = message
return True
self.object = obj
formState = self.updateFields()
# TODO: error handling
#errors = self.updateFields()
#if errors:
# self.view.setUp()
# for fieldName, message in errors.items():
# self.view.widgets[fieldName].error = message
# return True
self.request.response.redirect(self.view.virtualTargetUrl + '?version=this')
return False
@Lazy
def loopsRoot(self):
return self.view.loopsRoot
def updateFields(self):
obj = self.object
form = self.request.form
instance = self.instance
instance.template = self.schema
formState = instance.applyTemplate(data=form, fieldHandlers=self.fieldHandlers)
for k in form.keys():
if k.startswith(self.prefix):
fn = k[len(self.prefix):]
value = form[k]
if fn.startswith(self.conceptPrefix) and value:
self.collectConcepts(fn[len(self.conceptPrefix):], value)
if self.old or self.selected:
self.assignConcepts(obj)
notify(ObjectModifiedEvent(obj))
return formState
def updateFields(self, obj):
def handleFileUpload(self, context, value, fieldInstance, formState):
""" Special handler for fileupload fields;
value is a FileUpload instance.
"""
filename = getattr(value, 'filename', '')
if filename: # ignore if no filename present - no file uploaded
value = value.read()
contentType = guess_content_type(filename, value[:100])
if contentType:
ct = contentType[0]
self.request.form['form.contentType'] = ct
context.contentType = ct
setattr(context, fieldInstance.name, value)
context.localFilename = filename
@property
def fieldHandlers(self):
return dict(fileupload=self.handleFileUpload)
def xupdateFields(self): # obsolete
obj = self.object
errors = {}
form = self.request.form
ti = IType(obj).typeInterface
@ -407,11 +483,11 @@ class CreateObject(EditObject):
def update(self):
form = self.request.form
container = self.loopsRoot.getResourceManager()
title = form.get('form.title')
title = form.get('title')
if not title:
raise BadRequest('Title field is empty')
obj = Resource(title)
data = form.get('form.data')
data = form.get('data')
if data and isinstance(data, FileUpload):
name = getattr(data, 'filename', None)
# strip path from IE uploads:
@ -424,7 +500,8 @@ class CreateObject(EditObject):
tc = form.get('form.type') or '.loops/concepts/note'
obj.resourceType = self.loopsRoot.loopsTraverse(tc)
notify(ObjectCreatedEvent(obj))
self.updateFields(obj)
self.object = obj
self.updateFields()
self.request.response.redirect(self.view.virtualTargetUrl)
return False

View file

@ -14,10 +14,10 @@
</span>
</th></tr></tbody>
<tbody><tr><td colspan="5">
<tbody><tr><td colspan="5" style="padding-right: 15px">
<div id="form.fields">
<metal:fields use-macro="view/template/macros/fields" />
<!--<metal:fields use-macro="view/schemaMacros/fields" />-->
<!--<metal:fields use-macro="view/template/macros/fields" />-->
<metal:fields use-macro="view/schemaMacros/fields" />
</div>
</td></tr></tbody>
@ -64,7 +64,8 @@
<tbody><tr><td colspan="5">
<div id="form.fields">
<metal:fields use-macro="view/template/macros/fields" />
<!--<metal:fields use-macro="view/template/macros/fields" />-->
<metal:fields use-macro="view/schemaMacros/fields" />
</div>
</td></tr></tbody>

View file

@ -399,6 +399,8 @@
<adapter factory="cybertools.composer.schema.field.FieldInstance" />
<adapter factory="cybertools.composer.schema.field.NumberFieldInstance"
name="number" />
<adapter factory="cybertools.composer.schema.field.FileUploadFieldInstance"
name="fileupload" />
<adapter factory="loops.setup.SetupManager" />