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()
|
||||
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.
|
||||
(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.app.renderer import rest
|
||||
|
|
|
@ -142,16 +142,11 @@ class BaseView(GenericView):
|
|||
|
||||
@Lazy
|
||||
def typeProvider(self):
|
||||
type = self.type
|
||||
if type is not None:
|
||||
return type.typeProvider
|
||||
return self.type.typeProvider
|
||||
|
||||
@Lazy
|
||||
def typeInterface(self):
|
||||
provider = self.typeProvider
|
||||
if provider is not None:
|
||||
tc = ITypeConcept(provider)
|
||||
return tc.typeInterface
|
||||
return self.type.typeInterface
|
||||
|
||||
@Lazy
|
||||
def typeAdapter(self):
|
||||
|
@ -161,8 +156,7 @@ class BaseView(GenericView):
|
|||
|
||||
@Lazy
|
||||
def typeTitle(self):
|
||||
type = self.type
|
||||
return type is not None and type.title or None
|
||||
return self.type.title
|
||||
|
||||
@Lazy
|
||||
def typeUrl(self):
|
||||
|
|
|
@ -562,7 +562,15 @@
|
|||
<page
|
||||
name="create_object.html"
|
||||
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"
|
||||
/>
|
||||
|
||||
|
|
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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="dlg.create.search.type">Type:</label></td>
|
||||
<td><label for="form.concept.search.type">Type:</label></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
|
||||
string:setConceptTypeForComboBox(
|
||||
'dlg.create.search.type', 'dlg.create.search.text')">
|
||||
'form.concept.search.type', 'form.concept.search.text')">
|
||||
<tal:types repeat="type view/conceptTypesForSearch">
|
||||
<option value="loops:*"
|
||||
i18n:translate=""
|
||||
|
@ -48,10 +48,10 @@
|
|||
</tal:types>
|
||||
</select>
|
||||
</td>
|
||||
<td><label for="dlg.create.search.text">Search text:</label></td>
|
||||
<td><label for="form.concept.search.text">Search text:</label></td>
|
||||
<td>
|
||||
<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
|
||||
string:${context/@@absolute_url}/listConceptsForComboBox.js?searchString=%{searchString}&searchType=" />
|
||||
</td>
|
||||
|
|
|
@ -95,10 +95,12 @@ class NodeView(BaseView):
|
|||
|
||||
@Lazy
|
||||
def item(self):
|
||||
#target = self.virtualTargetObject # ignores page even for direktly assignd target
|
||||
target = self.request.annotations.get('loops.view', {}).get('target')
|
||||
# was there a .target... element in the URL?
|
||||
if target is not None:
|
||||
basicView = zapi.getMultiAdapter((target, self.request))
|
||||
# xxx: obsolete when self.targetObject is virtual target:
|
||||
return basicView.view
|
||||
return self.page
|
||||
|
||||
|
@ -139,6 +141,8 @@ class NodeView(BaseView):
|
|||
|
||||
@Lazy
|
||||
def targetObject(self):
|
||||
# xxx: use virtualTargetObject
|
||||
#return self.virtualTargetObject
|
||||
return self.context.target
|
||||
|
||||
@Lazy
|
||||
|
@ -158,7 +162,6 @@ class NodeView(BaseView):
|
|||
|
||||
def renderTarget(self):
|
||||
target = self.target
|
||||
#targetAdapter = target.typeAdapter
|
||||
return target is not None and target.render() or u''
|
||||
|
||||
@Lazy
|
||||
|
@ -242,9 +245,10 @@ class NodeView(BaseView):
|
|||
return item.context == self.context or item.context in self.parents
|
||||
|
||||
def targetDefaultView(self):
|
||||
target = self.request.annotations.get('loops.view', {}).get('target')
|
||||
if target is None:
|
||||
target = self.targetObject
|
||||
target = self.virtualTargetObject
|
||||
#target = self.request.annotations.get('loops.view', {}).get('target')
|
||||
#if target is None:
|
||||
# target = self.targetObject
|
||||
if target is not None:
|
||||
name = zapi.getDefaultViewName(target, self.request)
|
||||
targetView = zapi.getMultiAdapter((target, self.request),
|
||||
|
@ -258,7 +262,7 @@ class NodeView(BaseView):
|
|||
def virtualTargetObject(self):
|
||||
target = self.request.annotations.get('loops.view', {}).get('target')
|
||||
if target is None:
|
||||
target = self.targetObject
|
||||
target = self.context.target
|
||||
return target
|
||||
|
||||
@Lazy
|
||||
|
|
|
@ -25,30 +25,34 @@
|
|||
</div>
|
||||
<div tal:define="target nocall:item/target"
|
||||
tal:condition="nocall:target">
|
||||
<metal:editicons define-macro="editicons">
|
||||
<div class="subcolumn" id="xedit_icon"
|
||||
tal:condition="item/xeditable | nothing">
|
||||
<a href="#" title="Edit" style="padding: 5px"
|
||||
tal:attributes="href string:${item/realTargetUrl}/external_edit;
|
||||
title string:Edit '${target/title}' with External Editor"><img
|
||||
src="edit.gif" alt="Edit"
|
||||
tal:attributes="src context/++resource++edit.gif" /></a>
|
||||
</div>
|
||||
<div class="subcolumn" id="inlineedit_icon"
|
||||
tal:condition="item/inlineEditable">
|
||||
<a href="#" title="Edit" style="padding: 5px"
|
||||
tal:attributes="title string:Edit '${target/title}' with Inline Editor;
|
||||
onclick python: item.inlineEdit(id)"><img
|
||||
src="edit.gif" alt="Edit"
|
||||
tal:attributes="src context/++resource++edit.gif" /></a>
|
||||
</div>
|
||||
</metal:editicons>
|
||||
<tal:ignore condition="nothing">
|
||||
<metal:editicons define-macro="editicons">
|
||||
<div class="subcolumn" id="xedit_icon"
|
||||
tal:condition="item/xeditable | nothing">
|
||||
<a href="#" title="Edit" style="padding: 5px"
|
||||
tal:attributes="href string:${item/realTargetUrl}/external_edit;
|
||||
title string:Edit '${target/title}' with External Editor"><img
|
||||
src="edit.gif" alt="Edit"
|
||||
tal:attributes="src context/++resource++edit.gif" /></a>
|
||||
</div>
|
||||
<div class="subcolumn" id="inlineedit_icon"
|
||||
tal:condition="item/inlineEditable">
|
||||
<a href="#" title="Edit" style="padding: 5px"
|
||||
tal:attributes="title string:Edit '${target/title}' with Inline Editor;
|
||||
onclick python: item.inlineEdit(id)"><img
|
||||
src="edit.gif" alt="Edit"
|
||||
tal:attributes="src context/++resource++edit.gif" /></a>
|
||||
</div>
|
||||
</metal:editicons>
|
||||
</tal:ignore>
|
||||
<div class="content-1 subcolumn" id="1.body"
|
||||
tal:define="item nocall:target"
|
||||
tal:attributes="class string:content-$level;
|
||||
id id;
|
||||
ondblclick python: item.openEditWindow('configure.html')"
|
||||
tal:content="structure item/renderTarget">
|
||||
The body
|
||||
ondblclick python: target.openEditWindow('configure.html')">
|
||||
<metal:body use-macro="item/macro">
|
||||
The body
|
||||
</metal:body>
|
||||
</div>
|
||||
</div>
|
||||
</tal:body>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<metal:block define-macro="render">
|
||||
<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;
|
||||
id string:$itemNum.body;">
|
||||
<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
|
||||
|
||||
|
||||
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
|
||||
-------------------
|
||||
|
||||
|
|
4
type.py
4
type.py
|
@ -84,10 +84,6 @@ class LoopsType(BaseType):
|
|||
@Lazy
|
||||
def factory(self):
|
||||
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)
|
||||
|
||||
@Lazy
|
||||
|
|
Loading…
Add table
Reference in a new issue