First working version: add resource (note) via dojo.Dialog

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1358 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-09-23 10:54:32 +00:00
parent 2743e01d78
commit 63a13d6854
7 changed files with 137 additions and 35 deletions

View file

@ -346,20 +346,15 @@ We first need a view manager:
>>> nodeChecker = NamesChecker(('body',)) >>> nodeChecker = NamesChecker(('body',))
>>> defineChecker(Node, nodeChecker) >>> defineChecker(Node, nodeChecker)
>>> loopsRoot['views'] = ViewManager() >>> views = loopsRoot['views'] = ViewManager()
>>> views = loopsRoot['views']
The view space is typically built up with nodes; a node may be a top-level The view space is typically built up with nodes; a node may be a top-level
menu that may contain other nodes as menu or content items: menu that may contain other nodes as menu or content items:
>>> m1 = Node(u'Menu') >>> m1 = views['m1'] = Node(u'Menu')
>>> views['m1'] = m1 >>> m11 = m1['m11'] = Node(u'Zope')
>>> m11 = Node(u'Zope') >>> m111 = m11['m111'] = Node(u'Zope in General')
>>> m1['m11'] = m11 >>> m112 = m11['m112'] = Node(u'Zope 3')
>>> m111 = Node(u'Zope in General')
>>> m11['m111'] = m111
>>> m112 = Node(u'Zope 3')
>>> m11['m112'] = m112
>>> m112.title >>> m112.title
u'Zope 3' u'Zope 3'
>>> m112.description >>> m112.description
@ -616,8 +611,56 @@ to the bottom, and to the top.
>>> m11.keys() >>> m11.keys()
['m111', 'm114', 'm112', 'm113'] ['m111', 'm114', 'm112', 'm113']
End-user Forms
==============
The browser.form and related modules provide additional support for forms
that are shown in the end-user interface.
>>> from loops.browser.form import CreateObjectForm, CreateObject, ResourceNameChooser
>>> form = CreateObjectForm(m112, TestRequest)
>>> from loops.interfaces import INote, ITypeConcept
>>> from loops.type import TypeConcept
>>> from loops.resource import NoteAdapter
>>> component.provideAdapter(TypeConcept)
>>> component.provideAdapter(NoteAdapter)
>>> note_tc = concepts['note'] = Concept('Note')
>>> note_tc.conceptType = typeObject
>>> ITypeConcept(note_tc).typeInterface = INote
>>> component.provideAdapter(ResourceNameChooser)
>>> request = TestRequest(form={'form.title': 'Test Note'})
>>> view = NodeView(m112, request)
>>> cont = CreateObject(view, request)
>>> cont.update()
True
>>> sorted(resources.keys())
[...u'test_note'...]
>>> resources['test_note'].title
'Test Note'
If there is a concept selected in the combo box we assign this to the newly
created object:
>>> from loops import util
>>> topicUid = util.getUidForObject(topic)
>>> request = TestRequest(form={'form.title': 'Test Note',
... 'form.concept.search.text_selected': topicUid})
>>> view = NodeView(m112, request)
>>> cont = CreateObject(view, request)
>>> cont.update()
True
>>> sorted(resources.keys())
[...u'test_note-2'...]
>>> note = resources['test_note-2']
>>> sorted(t.__name__ for t in note.getConcepts())
[u'note', u'topic']
Import/Export Import/Export
------------- =============
Nodes may be exported to and loaded from external sources, typically Nodes may be exported to and loaded from external sources, typically
file representations that allow the transfer of nodes from one Zope file representations that allow the transfer of nodes from one Zope

View file

@ -574,6 +574,8 @@
permission="zope.ManageContent" permission="zope.ManageContent"
/> />
<zope:adapter factory="loops.browser.form.ResourceNameChooser" />
<!-- inner HTML views --> <!-- inner HTML views -->
<page <page

View file

@ -23,12 +23,25 @@ $Id$
""" """
from zope import component, interface, schema from zope import component, interface, schema
from zope.component import adapts
from zope.event import notify
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope.app.container.interfaces import INameChooser
from zope.app.container.contained import NameChooser
from zope.app.pagetemplate import ViewPageTemplateFile from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.formlib.form import Form, FormFields from zope.formlib.form import Form, FormFields
from zope.publisher.interfaces import BadRequest
from cybertools.ajax import innerHtml from cybertools.ajax import innerHtml
from cybertools.browser.controller import FormController from cybertools.browser.form import FormController
from cybertools.typology.interfaces import IType
from loops.interfaces import IResourceManager
from loops.browser.node import NodeView from loops.browser.node import NodeView
from loops.resource import Resource
from loops import util
from loops.util import _
class CreateObjectForm(NodeView, Form): class CreateObjectForm(NodeView, Form):
@ -39,7 +52,7 @@ class CreateObjectForm(NodeView, Form):
form_fields = FormFields( form_fields = FormFields(
schema.TextLine(__name__='title', title=_(u'Title')), schema.TextLine(__name__='title', title=_(u'Title')),
schema.Text(__name__='body', title=_(u'Body Text')), schema.Text(__name__='data', title=_(u'Body Text')),
schema.TextLine(__name__='linkUrl', title=_(u'Link'), required=False), schema.TextLine(__name__='linkUrl', title=_(u'Link'), required=False),
) )
@ -48,8 +61,10 @@ class CreateObjectForm(NodeView, Form):
def __init__(self, context, request): def __init__(self, context, request):
super(CreateObjectForm, self).__init__(context, request) super(CreateObjectForm, self).__init__(context, request)
def setUp(self):
self.setUpWidgets() self.setUpWidgets()
self.widgets['body'].height = 3 self.widgets['data'].height = 3
def __call__(self): def __call__(self):
return innerHtml(self) return innerHtml(self)
@ -57,22 +72,48 @@ class CreateObjectForm(NodeView, Form):
class CreateObject(FormController): class CreateObject(FormController):
@Lazy
def loopsRoot(self):
return self.view.loopsRoot
def update(self): def update(self):
prefix = 'form.' prefix = 'form.'
conceptPrefix = 'concept.'
form = self.request.form form = self.request.form
print 'updating...' obj = Resource()
# determine name container = self.loopsRoot.getResourceManager()
# create object, assign basic concepts (type, ...) title = form.get('form.title')
if not title:
raise BadRequest('Title field is empty')
name = INameChooser(container).chooseName(title, obj)
container[name] = obj
obj.resourceType = self.loopsRoot.getConceptManager()['note']
adapter = IType(obj).typeInterface(obj)
for k in form.keys(): for k in form.keys():
if k.startswith(prefix): if k.startswith(prefix):
fn = k[len(prefix):] fn = k[len(prefix):]
if fn in ('action',):
continue
value = form[k] value = form[k]
if fn.startswith('concept.search.'): if fn.startswith(conceptPrefix):
self.assignConcepts(fn, value) self.assignConcepts(obj, fn[len(conceptPrefix):], value)
else: else:
pass setattr(adapter, fn, value)
#setattr(obj, fn, value) notify(ObjectCreatedEvent(obj))
print fn, value notify(ObjectModifiedEvent(obj))
return True
def assignConcepts(self, fieldName, value): def assignConcepts(self, obj, fieldName, value):
pass if fieldName == 'search.text_selected':
concept = util.getObjectForUid(value)
obj.assignConcept(concept)
class ResourceNameChooser(NameChooser):
adapts(IResourceManager)
def chooseName(self, title, obj):
name = title.replace(' ', '_').lower()
name = super(ResourceNameChooser, self).chooseName(name, obj)
return name

View file

@ -1,6 +1,6 @@
<metal:block define-macro="create"> <metal:block define-macro="create">
<div> <div tal:define="dummy view/setUp">
<form method="get"> <form method="post">
<input type="hidden" name="form.action" value="create" <input type="hidden" name="form.action" value="create"
tal:attributes="value view/form_action" /> tal:attributes="value view/form_action" />
<table cellpadding="3" class="form"> <table cellpadding="3" class="form">
@ -10,6 +10,7 @@
i18n:translate="">Create Information Object</span> i18n:translate="">Create Information Object</span>
</th> </th>
</tr> </tr>
<tr tal:repeat="widget view/widgets"> <tr tal:repeat="widget view/widgets">
<td class="label" <td class="label"
tal:define="hint widget/hint"> tal:define="hint widget/hint">
@ -30,6 +31,7 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="4" class="headline">Assign Concept(s)</td> <td colspan="4" class="headline">Assign Concept(s)</td>
</tr> </tr>

View file

@ -26,12 +26,12 @@ from zope import schema, component
from zope.interface import Interface, Attribute, implements from zope.interface import Interface, Attribute, implements
from zope.app import traversing from zope.app import traversing
from zope.app.catalog.interfaces import ICatalog from zope.app.catalog.interfaces import ICatalog
from zope.app.intid.interfaces import IIntIds
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from loops.interfaces import IConcept from loops.interfaces import IConcept
from loops.common import AdapterBase from loops.common import AdapterBase
from loops.type import TypeInterfaceSourceList from loops.type import TypeInterfaceSourceList
from loops import util
from loops.util import _ from loops.util import _
@ -82,8 +82,7 @@ class BaseQuery(object):
if not uid: if not uid:
queue = list(self.queryConcepts(title=title, type=type)) queue = list(self.queryConcepts(title=title, type=type))
else: else:
intIds = component.getUtility(IIntIds) queue = [util.getObjectForUid(uid)]
queue = [intIds.getObject(int(uid))]
concepts = [] concepts = []
while queue: while queue:
c = queue.pop(0) c = queue.pop(0)

View file

@ -119,6 +119,7 @@ purposes fairly primitive) catalog and a resource we can search for:
... implements(ICatalog) ... implements(ICatalog)
... def searchResults(self, **criteria): ... def searchResults(self, **criteria):
... name = criteria.get('loops_title') ... name = criteria.get('loops_title')
... if name.endswith('*'): name = name[:-1]
... type = criteria.get('loops_type', ('resource',)) ... type = criteria.get('loops_type', ('resource',))
... if name: ... if name:
... if 'concept' in type[0]: ... if 'concept' in type[0]:
@ -156,10 +157,10 @@ Search via related concepts
We first have to prepare some test concepts (topics); we also assign our test We first have to prepare some test concepts (topics); we also assign our test
resource (rplone) from above to one of the topics: resource (rplone) from above to one of the topics:
>>> czope = concepts['zope'] = Concept('Zope') >>> czope = concepts['zope'] = Concept(u'Zope')
>>> czope2 = concepts['zope2'] = Concept('Zope 2') >>> czope2 = concepts['zope2'] = Concept(u'Zope 2')
>>> czope3 = concepts['zope3'] = Concept('Zope 3') >>> czope3 = concepts['zope3'] = Concept(u'Zope 3')
>>> cplone = concepts['plone'] = Concept('Plone') >>> cplone = concepts['plone'] = Concept(u'Plone')
>>> for c in (czope, czope2, czope3, cplone): >>> for c in (czope, czope2, czope3, cplone):
... c.conceptType = topic ... c.conceptType = topic
>>> czope.assignChild(czope2) >>> czope.assignChild(czope2)
@ -193,11 +194,11 @@ To support easy entry of concepts to search for we can preselect the available
concepts (optionally restricted to a certain type) by entering text parts concepts (optionally restricted to a certain type) by entering text parts
of the concepts' titles: of the concepts' titles:
>>> form = {'searchType': 'loops:concept:topic', 'searchString': u'zo'} >>> form = {'searchType': 'loops:concept:topic', 'searchString': u'zope'}
>>> request = TestRequest(form=form) >>> request = TestRequest(form=form)
>>> view = Search(page, request) >>> view = Search(page, request)
>>> view.listConcepts() >>> view.listConcepts()
'[]' "[['Zope', '23']]"
TODO - more to come... TODO - more to come...

14
util.py
View file

@ -22,6 +22,8 @@ Utility functions.
$Id$ $Id$
""" """
from zope import component
from zope.app.intid.interfaces import IIntIds
from zope.interface import directlyProvides, directlyProvidedBy from zope.interface import directlyProvides, directlyProvidedBy
from zope.i18nmessageid import MessageFactory from zope.i18nmessageid import MessageFactory
from zope.schema import vocabulary from zope.schema import vocabulary
@ -53,3 +55,15 @@ def nl2br(text):
return '<br />\n'.join(x.replace('\r', '') for x in text.split('\n')) return '<br />\n'.join(x.replace('\r', '') for x in text.split('\n'))
else: # gracefully handle Mac line endings else: # gracefully handle Mac line endings
return '<br />\n'.join(text.split('\r')) return '<br />\n'.join(text.split('\r'))
def getObjectForUid(uid):
if uid == '*': # wild card
return '*'
intIds = component.getUtility(IIntIds)
return intIds.getObject(int(uid))
def getUidForObject(obj):
if obj == '*': # wild card
return '*'
intIds = component.getUtility(IIntIds)
return intIds.queryId(obj)