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'] >>> note_tc = concepts['note']
>>> component.provideAdapter(NameChooser) >>> component.provideAdapter(NameChooser)
>>> request = TestRequest(form={'form.title': u'Test Note', >>> request = TestRequest(form={'title': u'Test Note',
... 'form.type': u'.loops/concepts/note'}) ... 'form.type': u'.loops/concepts/note'})
>>> view = NodeView(m112, request) >>> view = NodeView(m112, request)
>>> cont = CreateObject(view, request) >>> cont = CreateObject(view, request)
@ -668,7 +668,7 @@ created object:
>>> from loops import util >>> from loops import util
>>> topicUid = util.getUidForObject(topic) >>> topicUid = util.getUidForObject(topic)
>>> predicateUid = util.getUidForObject(concepts.getDefaultPredicate()) >>> 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.type': u'.loops/concepts/note',
... 'form.assignments.selected': ... 'form.assignments.selected':
... [':'.join((topicUid, predicateUid))]}) ... [':'.join((topicUid, predicateUid))]})
@ -711,19 +711,21 @@ The new technique uses the ``fields`` and ``data`` attributes...
>>> for f in view.fields: >>> for f in view.fields:
... print f.name, f.fieldType, f.required, f.vocabulary ... print f.name, f.fieldType, f.required, f.vocabulary
title textline True None title textline True None
description textarea False None
data textarea False None data textarea False None
contentType dropdown True <...SimpleVocabulary object...> contentType dropdown True <...SimpleVocabulary object...>
linkUrl textline False None linkUrl textline False None
>>> view.data >>> view.data
{'linkUrl': None, 'contentType': u'', 'data': '', 'description': '', {'linkUrl': None, 'contentType': u'', 'data': '',
'title': u'Test Note'} 'title': u'Test Note'}
The object is changed via a FormController adapter created for The object is changed via a FormController adapter created for
a NodeView. 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) >>> view = NodeView(m112, request)
>>> cont = EditObject(view, request) >>> cont = EditObject(view, request)
>>> cont.update() >>> 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.composer.schema.util import getSchemaFromInterface
from cybertools.typology.interfaces import IType, ITypeManager from cybertools.typology.interfaces import IType, ITypeManager
from loops.common import adapted 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 IConcept, IResourceManager, IDocument
from loops.interfaces import IFile, IExternalFile, INote, ITextDocument from loops.interfaces import IFile, IExternalFile, INote, ITextDocument
from loops.browser.node import NodeView from loops.browser.node import NodeView
@ -107,7 +107,13 @@ class ObjectForm(NodeView):
@Lazy @Lazy
def fields(self): 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 @Lazy
def data(self): def data(self):
@ -130,7 +136,7 @@ class ObjectForm(NodeView):
def form_fields(self): def form_fields(self):
ifc = self.typeInterface ifc = self.typeInterface
ff = FormFields(ifc) ff = FormFields(ifc)
if self.typeInterface in widgetControllers: if ifc in widgetControllers:
wc = widgetControllers[ifc](self.context, self.request) wc = widgetControllers[ifc](self.context, self.request)
ff = wc.modifyFormFields(ff) ff = wc.modifyFormFields(ff)
return ff return ff
@ -194,6 +200,9 @@ class WidgetController(object):
self.context = context self.context = context
self.request = request self.request = request
def modifySchemaFields(self, fields):
pass
def modifyFormFields(self, formFields): def modifyFormFields(self, formFields):
return formFields return formFields
@ -203,6 +212,10 @@ class WidgetController(object):
class NoteWidgetController(WidgetController): class NoteWidgetController(WidgetController):
def modifySchemaFields(self, fields):
del fields['description']
fields.data.height = 5
def modifyFormFields(self, formFields): def modifyFormFields(self, formFields):
return formFields.omit('description') return formFields.omit('description')
@ -212,6 +225,11 @@ class NoteWidgetController(WidgetController):
class FileWidgetController(WidgetController): class FileWidgetController(WidgetController):
def modifySchemaFields(self, fields):
if self.request.principal.id != 'rootadmin':
del fields['contentType']
def modifyFormFields(self, formFields): def modifyFormFields(self, formFields):
if self.request.principal.id == 'rootadmin': if self.request.principal.id == 'rootadmin':
return formFields return formFields
@ -289,7 +307,8 @@ class CreateObjectForm(ObjectForm, Form):
class InnerForm(CreateObjectForm): class InnerForm(CreateObjectForm):
@property @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 # processing form input
@ -302,6 +321,27 @@ class EditObject(FormController):
old = None old = None
selected = 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): def update(self):
# create new version if necessary # create new version if necessary
target = self.view.virtualTargetObject target = self.view.virtualTargetObject
@ -310,20 +350,56 @@ class EditObject(FormController):
# make sure new version is used by the view # make sure new version is used by the view
self.view.virtualTargetObject = obj self.view.virtualTargetObject = obj
self.request.annotations['loops.view']['target'] = obj self.request.annotations['loops.view']['target'] = obj
errors = self.updateFields(obj) self.object = obj
if errors: formState = self.updateFields()
self.view.setUp() # TODO: error handling
for fieldName, message in errors.items(): #errors = self.updateFields()
self.view.widgets[fieldName].error = message #if errors:
return True # 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') self.request.response.redirect(self.view.virtualTargetUrl + '?version=this')
return False return False
@Lazy def updateFields(self):
def loopsRoot(self): obj = self.object
return self.view.loopsRoot 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 = {} errors = {}
form = self.request.form form = self.request.form
ti = IType(obj).typeInterface ti = IType(obj).typeInterface
@ -407,11 +483,11 @@ class CreateObject(EditObject):
def update(self): def update(self):
form = self.request.form form = self.request.form
container = self.loopsRoot.getResourceManager() container = self.loopsRoot.getResourceManager()
title = form.get('form.title') title = form.get('title')
if not title: if not title:
raise BadRequest('Title field is empty') raise BadRequest('Title field is empty')
obj = Resource(title) obj = Resource(title)
data = form.get('form.data') data = form.get('data')
if data and isinstance(data, FileUpload): if data and isinstance(data, FileUpload):
name = getattr(data, 'filename', None) name = getattr(data, 'filename', None)
# strip path from IE uploads: # strip path from IE uploads:
@ -424,7 +500,8 @@ class CreateObject(EditObject):
tc = form.get('form.type') or '.loops/concepts/note' tc = form.get('form.type') or '.loops/concepts/note'
obj.resourceType = self.loopsRoot.loopsTraverse(tc) obj.resourceType = self.loopsRoot.loopsTraverse(tc)
notify(ObjectCreatedEvent(obj)) notify(ObjectCreatedEvent(obj))
self.updateFields(obj) self.object = obj
self.updateFields()
self.request.response.redirect(self.view.virtualTargetUrl) self.request.response.redirect(self.view.virtualTargetUrl)
return False return False

View file

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

View file

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