clean-up view control by node_macros; starting form input processing with FormController
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1354 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
980114d649
commit
cb194f0f24
10 changed files with 133 additions and 46 deletions
|
@ -536,6 +536,8 @@ A node object provides the targetSchema of its target:
|
||||||
A node's target is rendered using the NodeView's renderTargetBody()
|
A node's target is rendered using the NodeView's renderTargetBody()
|
||||||
method. This makes use of a browser view registered for the target interface,
|
method. This makes use of a browser view registered for the target interface,
|
||||||
and of a lot of other stuff needed for the rendering machine.
|
and of a lot of other stuff needed for the rendering machine.
|
||||||
|
(Note: renderTarget is obsolete - we now use a macro provided by the target's
|
||||||
|
view for rendering.)
|
||||||
|
|
||||||
>>> from zope.component.interfaces import IFactory
|
>>> from zope.component.interfaces import IFactory
|
||||||
>>> from zope.app.renderer import rest
|
>>> from zope.app.renderer import rest
|
||||||
|
|
|
@ -142,16 +142,11 @@ class BaseView(GenericView):
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def typeProvider(self):
|
def typeProvider(self):
|
||||||
type = self.type
|
return self.type.typeProvider
|
||||||
if type is not None:
|
|
||||||
return type.typeProvider
|
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def typeInterface(self):
|
def typeInterface(self):
|
||||||
provider = self.typeProvider
|
return self.type.typeInterface
|
||||||
if provider is not None:
|
|
||||||
tc = ITypeConcept(provider)
|
|
||||||
return tc.typeInterface
|
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def typeAdapter(self):
|
def typeAdapter(self):
|
||||||
|
@ -161,8 +156,7 @@ class BaseView(GenericView):
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def typeTitle(self):
|
def typeTitle(self):
|
||||||
type = self.type
|
return self.type.title
|
||||||
return type is not None and type.title or None
|
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def typeUrl(self):
|
def typeUrl(self):
|
||||||
|
|
|
@ -562,7 +562,15 @@
|
||||||
<page
|
<page
|
||||||
name="create_object.html"
|
name="create_object.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.node.CreateObject"
|
class="loops.browser.form.CreateObjectForm"
|
||||||
|
permission="zope.ManageContent"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<zope:adapter
|
||||||
|
name="create_resource"
|
||||||
|
for="loops.browser.node.NodeView
|
||||||
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
|
factory="loops.browser.form.CreateObject"
|
||||||
permission="zope.ManageContent"
|
permission="zope.ManageContent"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
61
browser/form.py
Normal file
61
browser/form.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
View class for Node objects.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope import component, interface, schema
|
||||||
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
from zope.formlib.form import Form, FormFields
|
||||||
|
from cybertools.ajax import innerHtml
|
||||||
|
from cybertools.browser.controller import FormController
|
||||||
|
from loops.browser.node import NodeView
|
||||||
|
|
||||||
|
class CreateObjectForm(NodeView, Form):
|
||||||
|
|
||||||
|
template = ViewPageTemplateFile('form_macros.pt')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def macro(self): return self.template.macros['create']
|
||||||
|
|
||||||
|
form_fields = FormFields(
|
||||||
|
schema.TextLine(__name__='title', title=_(u'Title')),
|
||||||
|
schema.Text(__name__='body', title=_(u'Body Text')),
|
||||||
|
schema.TextLine(__name__='linkUrl', title=_(u'Link'), required=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
title = _(u'Enter Note')
|
||||||
|
form_action = 'create_resource'
|
||||||
|
|
||||||
|
def __init__(self, context, request):
|
||||||
|
super(CreateObjectForm, self).__init__(context, request)
|
||||||
|
self.setUpWidgets()
|
||||||
|
self.widgets['body'].height = 3
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
return innerHtml(self)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateObject(FormController):
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
print 'updating...'
|
|
@ -34,12 +34,12 @@
|
||||||
<td colspan="4" class="headline">Assign Concept(s)</td>
|
<td colspan="4" class="headline">Assign Concept(s)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><label for="dlg.create.search.type">Type:</label></td>
|
<td><label for="form.concept.search.type">Type:</label></td>
|
||||||
<td>
|
<td>
|
||||||
<select name="dlg.create.search.type" id="dlg.create.search.type"
|
<select name="form.concept.search.type" id="form.concept.search.type"
|
||||||
tal:attributes="onChange
|
tal:attributes="onChange
|
||||||
string:setConceptTypeForComboBox(
|
string:setConceptTypeForComboBox(
|
||||||
'dlg.create.search.type', 'dlg.create.search.text')">
|
'form.concept.search.type', 'form.concept.search.text')">
|
||||||
<tal:types repeat="type view/conceptTypesForSearch">
|
<tal:types repeat="type view/conceptTypesForSearch">
|
||||||
<option value="loops:*"
|
<option value="loops:*"
|
||||||
i18n:translate=""
|
i18n:translate=""
|
||||||
|
@ -48,10 +48,10 @@
|
||||||
</tal:types>
|
</tal:types>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td><label for="dlg.create.search.text">Search text:</label></td>
|
<td><label for="form.concept.search.text">Search text:</label></td>
|
||||||
<td>
|
<td>
|
||||||
<input dojoType="comboBox" mode="remote" autoComplete="False"
|
<input dojoType="comboBox" mode="remote" autoComplete="False"
|
||||||
name="dlg.create.search.text" id="dlg.create.search.text"
|
name="form.concept.search.text" id="form.concept.search.text"
|
||||||
tal:attributes="dataUrl
|
tal:attributes="dataUrl
|
||||||
string:${context/@@absolute_url}/listConceptsForComboBox.js?searchString=%{searchString}&searchType=" />
|
string:${context/@@absolute_url}/listConceptsForComboBox.js?searchString=%{searchString}&searchType=" />
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -95,10 +95,12 @@ class NodeView(BaseView):
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def item(self):
|
def item(self):
|
||||||
|
#target = self.virtualTargetObject # ignores page even for direktly assignd target
|
||||||
target = self.request.annotations.get('loops.view', {}).get('target')
|
target = self.request.annotations.get('loops.view', {}).get('target')
|
||||||
# was there a .target... element in the URL?
|
# was there a .target... element in the URL?
|
||||||
if target is not None:
|
if target is not None:
|
||||||
basicView = zapi.getMultiAdapter((target, self.request))
|
basicView = zapi.getMultiAdapter((target, self.request))
|
||||||
|
# xxx: obsolete when self.targetObject is virtual target:
|
||||||
return basicView.view
|
return basicView.view
|
||||||
return self.page
|
return self.page
|
||||||
|
|
||||||
|
@ -139,6 +141,8 @@ class NodeView(BaseView):
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def targetObject(self):
|
def targetObject(self):
|
||||||
|
# xxx: use virtualTargetObject
|
||||||
|
#return self.virtualTargetObject
|
||||||
return self.context.target
|
return self.context.target
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
@ -158,7 +162,6 @@ class NodeView(BaseView):
|
||||||
|
|
||||||
def renderTarget(self):
|
def renderTarget(self):
|
||||||
target = self.target
|
target = self.target
|
||||||
#targetAdapter = target.typeAdapter
|
|
||||||
return target is not None and target.render() or u''
|
return target is not None and target.render() or u''
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
@ -242,9 +245,10 @@ class NodeView(BaseView):
|
||||||
return item.context == self.context or item.context in self.parents
|
return item.context == self.context or item.context in self.parents
|
||||||
|
|
||||||
def targetDefaultView(self):
|
def targetDefaultView(self):
|
||||||
target = self.request.annotations.get('loops.view', {}).get('target')
|
target = self.virtualTargetObject
|
||||||
if target is None:
|
#target = self.request.annotations.get('loops.view', {}).get('target')
|
||||||
target = self.targetObject
|
#if target is None:
|
||||||
|
# target = self.targetObject
|
||||||
if target is not None:
|
if target is not None:
|
||||||
name = zapi.getDefaultViewName(target, self.request)
|
name = zapi.getDefaultViewName(target, self.request)
|
||||||
targetView = zapi.getMultiAdapter((target, self.request),
|
targetView = zapi.getMultiAdapter((target, self.request),
|
||||||
|
@ -258,7 +262,7 @@ class NodeView(BaseView):
|
||||||
def virtualTargetObject(self):
|
def virtualTargetObject(self):
|
||||||
target = self.request.annotations.get('loops.view', {}).get('target')
|
target = self.request.annotations.get('loops.view', {}).get('target')
|
||||||
if target is None:
|
if target is None:
|
||||||
target = self.targetObject
|
target = self.context.target
|
||||||
return target
|
return target
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div tal:define="target nocall:item/target"
|
<div tal:define="target nocall:item/target"
|
||||||
tal:condition="nocall:target">
|
tal:condition="nocall:target">
|
||||||
|
<tal:ignore condition="nothing">
|
||||||
<metal:editicons define-macro="editicons">
|
<metal:editicons define-macro="editicons">
|
||||||
<div class="subcolumn" id="xedit_icon"
|
<div class="subcolumn" id="xedit_icon"
|
||||||
tal:condition="item/xeditable | nothing">
|
tal:condition="item/xeditable | nothing">
|
||||||
|
@ -43,12 +44,15 @@
|
||||||
tal:attributes="src context/++resource++edit.gif" /></a>
|
tal:attributes="src context/++resource++edit.gif" /></a>
|
||||||
</div>
|
</div>
|
||||||
</metal:editicons>
|
</metal:editicons>
|
||||||
|
</tal:ignore>
|
||||||
<div class="content-1 subcolumn" id="1.body"
|
<div class="content-1 subcolumn" id="1.body"
|
||||||
|
tal:define="item nocall:target"
|
||||||
tal:attributes="class string:content-$level;
|
tal:attributes="class string:content-$level;
|
||||||
id id;
|
id id;
|
||||||
ondblclick python: item.openEditWindow('configure.html')"
|
ondblclick python: target.openEditWindow('configure.html')">
|
||||||
tal:content="structure item/renderTarget">
|
<metal:body use-macro="item/macro">
|
||||||
The body
|
The body
|
||||||
|
</metal:body>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</tal:body>
|
</tal:body>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<metal:block define-macro="render">
|
<metal:block define-macro="render">
|
||||||
<div tal:attributes="ondblclick python: item.openEditWindow('configure.html')">
|
<div tal:attributes="ondblclick python: item.openEditWindow('configure.html')">
|
||||||
<h3 tal:content="item/title">Title</h3>
|
<h1 tal:content="item/title">Title</h1>
|
||||||
<tal:body define="itemNum view/itemNum;
|
<tal:body define="itemNum view/itemNum;
|
||||||
id string:$itemNum.body;">
|
id string:$itemNum.body;">
|
||||||
<tal:edit define="target nocall:item;
|
<tal:edit define="target nocall:item;
|
||||||
|
|
18
helpers.txt
18
helpers.txt
|
@ -277,6 +277,24 @@ i.e. the 'topic' concept, via an adapter:
|
||||||
True
|
True
|
||||||
|
|
||||||
|
|
||||||
|
Simple access to type information with BaseView
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
loops browser views are typically based on a common parent class, BaseView.
|
||||||
|
BaseView provides simple access to a lot of information often needed for
|
||||||
|
browser views; among others also some important informations about the
|
||||||
|
context object's type:
|
||||||
|
|
||||||
|
>>> from loops.browser.common import BaseView
|
||||||
|
>>> view = BaseView(cc1, TestRequest)
|
||||||
|
>>> view.typeTitle
|
||||||
|
u'Topic'
|
||||||
|
>>> view.typeInterface
|
||||||
|
<InterfaceClass ...ITopic>
|
||||||
|
>>> view.typeAdapter
|
||||||
|
<Topic object ...>
|
||||||
|
|
||||||
|
|
||||||
Concepts as queries
|
Concepts as queries
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
4
type.py
4
type.py
|
@ -84,10 +84,6 @@ class LoopsType(BaseType):
|
||||||
@Lazy
|
@Lazy
|
||||||
def factory(self):
|
def factory(self):
|
||||||
ti = self.typeInterface
|
ti = self.typeInterface
|
||||||
#if ti is not None:
|
|
||||||
# fn = getattr(ti, 'factoryName', None)
|
|
||||||
# if fn:
|
|
||||||
# return self.factoryMapping.get(fn, Concept)
|
|
||||||
return self.factoryMapping.get(self.qualifiers[0], Concept)
|
return self.factoryMapping.get(self.qualifiers[0], Concept)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
|
Loading…
Add table
Reference in a new issue