work in progress: preparing dojo dialog forms for implementing validation

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1965 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-08-27 17:33:07 +00:00
parent 4ccf4d033c
commit 4d645cc695
4 changed files with 68 additions and 16 deletions

View file

@ -43,7 +43,7 @@ from cybertools.browser.form import FormController
from cybertools.typology.interfaces import IType, ITypeManager from cybertools.typology.interfaces import IType, ITypeManager
from loops.concept import ResourceRelation from loops.concept import ResourceRelation
from loops.interfaces import IConcept, IResourceManager, IDocument from loops.interfaces import IConcept, IResourceManager, IDocument
from loops.interfaces import IFile, IExternalFile, INote from loops.interfaces import IFile, IExternalFile, INote, ITextDocument
from loops.browser.node import NodeView from loops.browser.node import NodeView
from loops.browser.concept import ConceptRelationView from loops.browser.concept import ConceptRelationView
from loops.query import ConceptQuery from loops.query import ConceptQuery
@ -80,10 +80,14 @@ class ObjectForm(NodeView):
template = ViewPageTemplateFile('form_macros.pt') template = ViewPageTemplateFile('form_macros.pt')
_isSetUp = False
def __init__(self, context, request): def __init__(self, context, request):
super(ObjectForm, self).__init__(context, request) super(ObjectForm, self).__init__(context, request)
def setUp(self): def setUp(self):
if self._isSetUp:
return
self.setUpWidgets() self.setUpWidgets()
desc = self.widgets.get('description') desc = self.widgets.get('description')
if desc: if desc:
@ -91,6 +95,7 @@ class ObjectForm(NodeView):
if self.typeInterface in widgetControllers: if self.typeInterface in widgetControllers:
wc = widgetControllers[self.typeInterface](self.context, self.request) wc = widgetControllers[self.typeInterface](self.context, self.request)
wc.modifyWidgetSetup(self.widgets) wc.modifyWidgetSetup(self.widgets)
self._isSetUp = True
def __call__(self): def __call__(self):
response = self.request.response response = self.request.response
@ -175,6 +180,7 @@ class EditObjectForm(ObjectForm, EditForm):
def __init__(self, context, request): def __init__(self, context, request):
super(EditObjectForm, self).__init__(context, request) super(EditObjectForm, self).__init__(context, request)
self.url = self.url # keep virtual target URL
self.context = self.virtualTargetObject self.context = self.virtualTargetObject
@Lazy @Lazy
@ -213,7 +219,8 @@ class CreateObjectForm(ObjectForm, Form):
t = self.loopsRoot.loopsTraverse(typeToken) t = self.loopsRoot.loopsTraverse(typeToken)
ifc = removeSecurityProxy(ITypeConcept(t).typeInterface) ifc = removeSecurityProxy(ITypeConcept(t).typeInterface)
else: else:
ifc = INote #ifc = INote
ifc = ITextDocument
self.typeInterface = ifc self.typeInterface = ifc
ff = FormFields(ifc) ff = FormFields(ifc)
#ff['data'].custom_widget = UploadWidget #ff['data'].custom_widget = UploadWidget
@ -256,16 +263,21 @@ 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
self.updateFields(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.request.response.redirect(self.view.virtualTargetUrl + '?version=this') self.request.response.redirect(self.view.virtualTargetUrl + '?version=this')
return False return False
#return True
@Lazy @Lazy
def loopsRoot(self): def loopsRoot(self):
return self.view.loopsRoot return self.view.loopsRoot
def updateFields(self, obj): def updateFields(self, obj):
errors = {}
form = self.request.form form = self.request.form
ti = IType(obj).typeInterface ti = IType(obj).typeInterface
if ti is not None: if ti is not None:
@ -273,6 +285,7 @@ class EditObject(FormController):
else: else:
adapted = obj adapted = obj
for k in form.keys(): for k in form.keys():
# TODO: use self.view.form_fields
if k.startswith(self.prefix): if k.startswith(self.prefix):
fn = k[len(self.prefix):] fn = k[len(self.prefix):]
if fn in ('action', 'type', 'data.used') or fn.endswith('-empty-marker'): if fn in ('action', 'type', 'data.used') or fn.endswith('-empty-marker'):
@ -295,10 +308,16 @@ class EditObject(FormController):
self.request.form['form.contentType'] = ct self.request.form['form.contentType'] = ct
adapted.contentType = ct adapted.contentType = ct
adapted.localFilename = filename adapted.localFilename = filename
setattr(adapted, fn, value) if fn == 'title' and not value:
# TODO: provide general validation mechanism
errors[fn] = 'Field %s must not be empty' % fn
else:
# TODO: provide unmarshalling depending on field type
setattr(adapted, fn, value)
if self.old or self.selected: if self.old or self.selected:
self.assignConcepts(obj) self.assignConcepts(obj)
notify(ObjectModifiedEvent(obj)) notify(ObjectModifiedEvent(obj))
return errors
def collectConcepts(self, fieldName, value): def collectConcepts(self, fieldName, value):
if self.old is None: self.old = [] if self.old is None: self.old = []
@ -361,5 +380,4 @@ class CreateObject(EditObject):
self.updateFields(obj) self.updateFields(obj)
self.request.response.redirect(self.view.virtualTargetUrl) self.request.response.redirect(self.view.virtualTargetUrl)
return False return False
#return True

View file

@ -2,7 +2,7 @@
$Id$ --> $Id$ -->
<metal:block define-macro="edit" i18n:domain="loops"> <metal:block define-macro="edit" i18n:domain="loops">
<form method="post" enctype="multipart/form-data"> <form method="post" enctype="multipart/form-data" id="dialog_form">
<input type="hidden" name="form.action" value="edit" <input type="hidden" name="form.action" value="edit"
tal:attributes="value view/form_action" /> tal:attributes="value view/form_action" />
<input type="hidden" name="version" <input type="hidden" name="version"
@ -55,7 +55,7 @@
tal:attributes="value type/token; tal:attributes="value type/token;
selected python: selected python:
type.token == (request.get('form.type') type.token == (request.get('form.type')
or '.loops/concepts/note')"> or '.loops/concepts/textdocument')">
Note Note
</option> </option>
</select> </select>
@ -81,8 +81,11 @@
</metal:block> </metal:block>
<metal:fields define-macro="fields"> <metal:fields define-macro="fields"
<tal:block tal:define="dummy view/setUp"> tal:define="show view/update">
<tal:show condition="show">
<div id="form_fields"
tal:define="dummy view/setUp">
<table width="100%"> <table width="100%">
<tr tal:repeat="widget view/widgets"> <tr tal:repeat="widget view/widgets">
<td class="label" width="10%" <td class="label" width="10%"
@ -104,7 +107,8 @@
</td> </td>
</tr> </tr>
</table> </table>
</tal:block> </div>
</tal:show>
</metal:fields> </metal:fields>
@ -205,8 +209,12 @@
<tr metal:define-macro="buttons" i18n:domain=""> <tr metal:define-macro="buttons" i18n:domain="">
<td colspan="5" <td colspan="5"
tal:define="dlgName view/dialog_name"> tal:define="dlgName view/dialog_name">
<input type="submit" value="Save" onClick="dlg.hide()" class="submit" <input value="Save" type="submit"
i18n:attributes="value" i18n:attributes="value"
xtal:attributes="onClick
string:return submitReplacingOrReloading(
'form_fields', 'dialog_form',
'${view/virtualTargetUrl}/@@inner_form.html')"
tal:attributes="onClick string:dialogs['$dlgName'].hide()"> tal:attributes="onClick string:dialogs['$dlgName'].hide()">
<input type="button" value="Cancel" onClick="dlg.hide();" <input type="button" value="Cancel" onClick="dlg.hide();"
i18n:attributes="value" i18n:attributes="value"

View file

@ -28,6 +28,28 @@ function submitReplacing(targetId, formId, actionUrl) {
return false; return false;
} }
function submitReplacingOrReloading(targetId, formId, actionUrl) {
node = dojo.byId(targetId);
var args = {
url: actionUrl,
formNode: dojo.byId(formId),
method: 'post',
mimetype: "text/html"
};
args.load = function (t, d, e) {
if (d.length < 10) {
document.location.reload(false);
} else {
while (node.firstChild) {
dojo.dom.destroyNode(node.firstChild);
}
node.innerHTML = d;
}
};
dojo.io.bind(args);
return false;
}
function inlineEdit(id, saveUrl) { function inlineEdit(id, saveUrl) {
var iconNode = dojo.byId('inlineedit_icon'); var iconNode = dojo.byId('inlineedit_icon');
iconNode.style.visibility = 'hidden'; iconNode.style.visibility = 'hidden';

View file

@ -220,18 +220,22 @@
</a> </a>
</div> </div>
<div> <div>
<a href="#" i18n:translate="" <a href="create_object.html" i18n:translate=""
onclick="objectDialog('create', 'create_object.html'); return false;" onclick="objectDialog('create', 'create_object.html'); return false;"
tal:attributes="onclick string:objectDialog('create', '$url/create_object.html');; return false;;"> tal:attributes="onClick
string:objectDialog('create', '$url/create_object.html');;
return false;;">
Create Resource... Create Resource...
</a> </a>
</div> </div>
<div tal:condition="view/hasEditableTarget"> <div tal:condition="view/hasEditableTarget">
<a href="#" i18n:translate="" <a href="edit_object.html" i18n:translate=""
onclick="objectDialog('edit', 'edit_object.html'); return false;" onclick="objectDialog('edit', 'edit_object.html'); return false;"
tal:define="version request/version|nothing; tal:define="version request/version|nothing;
versionPar python: version and '?version=' + version or ''" versionPar python: version and '?version=' + version or ''"
tal:attributes="onclick string:objectDialog('edit', '$url/edit_object.html$versionPar');; return false;;"> tal:attributes="onClick
string:objectDialog('edit', '$url/edit_object.html$versionPar');;
return false;;">
Edit Resource... Edit Resource...
</a> </a>
</div> </div>