first running version of creating and roundtrip editing resources via dojo.Dialog

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1359 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-09-24 13:59:56 +00:00
parent 63a13d6854
commit 94a14aac45
10 changed files with 272 additions and 107 deletions

View file

@ -631,7 +631,8 @@ that are shown in the end-user interface.
>>> ITypeConcept(note_tc).typeInterface = INote >>> ITypeConcept(note_tc).typeInterface = INote
>>> component.provideAdapter(ResourceNameChooser) >>> component.provideAdapter(ResourceNameChooser)
>>> request = TestRequest(form={'form.title': 'Test Note'}) >>> request = TestRequest(form={'form.title': 'Test Note',
... 'form.type': '.loops/concepts/note'})
>>> view = NodeView(m112, request) >>> view = NodeView(m112, request)
>>> cont = CreateObject(view, request) >>> cont = CreateObject(view, request)
>>> cont.update() >>> cont.update()
@ -647,7 +648,8 @@ created object:
>>> from loops import util >>> from loops import util
>>> topicUid = util.getUidForObject(topic) >>> topicUid = util.getUidForObject(topic)
>>> request = TestRequest(form={'form.title': 'Test Note', >>> request = TestRequest(form={'form.title': 'Test Note',
... 'form.concept.search.text_selected': topicUid}) ... 'form.type': '.loops/concepts/note',
... 'form.concept.search.text_selected': str(topicUid)})
>>> view = NodeView(m112, request) >>> view = NodeView(m112, request)
>>> cont = CreateObject(view, request) >>> cont = CreateObject(view, request)
>>> cont.update() >>> cont.update()

View file

@ -42,6 +42,7 @@ from cybertools.browser.view import GenericView
from cybertools.relation.interfaces import IRelationRegistry from cybertools.relation.interfaces import IRelationRegistry
from cybertools.typology.interfaces import IType, ITypeManager from cybertools.typology.interfaces import IType, ITypeManager
from loops.interfaces import IView from loops.interfaces import IView
from loops.resource import Resource
from loops.type import ITypeConcept from loops.type import ITypeConcept
from loops import util from loops import util
from loops.util import _ from loops.util import _
@ -170,6 +171,15 @@ class BaseView(GenericView):
for o in objs: for o in objs:
yield BaseView(o, request) yield BaseView(o, request)
def resourceTypes(self):
return util.KeywordVocabulary([(t.token, t.title)
for t in ITypeManager(self.context).listTypes(('resource',))
if t.factory == Resource])
def conceptTypes(self):
return util.KeywordVocabulary([(t.token, t.title)
for t in ITypeManager(self.context).listTypes(('concept',))])
def typesForSearch(self): def typesForSearch(self):
general = [('loops:resource:*', 'Any Resource'), general = [('loops:resource:*', 'Any Resource'),
('loops:concept:*', 'Any Concept'),] ('loops:concept:*', 'Any Concept'),]
@ -179,9 +189,13 @@ class BaseView(GenericView):
def conceptTypesForSearch(self): def conceptTypesForSearch(self):
general = [('loops:concept:*', 'Any Concept'),] general = [('loops:concept:*', 'Any Concept'),]
return util.KeywordVocabulary(general + sorted([(t.tokenForSearch, t.title) return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
for t in ITypeManager(self.context).types for t in ITypeManager(self.context).listTypes(('concept',))])
if 'concept' in t.qualifiers]))
def resourceTypesForSearch(self):
general = [('loops:resource:*', 'Any Resource'),]
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
for t in ITypeManager(self.context).listTypes(('resource',))])
@Lazy @Lazy
def uniqueId(self): def uniqueId(self):

View file

@ -244,24 +244,6 @@ class ConceptConfigureView(ConceptView):
result = [r for r in result if r.conceptType is None] result = [r for r in result if r.conceptType is None]
return self.viewIterator(result) return self.viewIterator(result)
def conceptTypes(self):
return util.KeywordVocabulary([(t.token, t.title)
for t in ITypeManager(self.context).listTypes(('concept',))])
def conceptTypesForSearch(self):
general = [('loops:concept:*', 'Any'),]
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
for t in ITypeManager(self.context).listTypes(('concept',))])
def resourceTypes(self):
return util.KeywordVocabulary([(t.token, t.title)
for t in ITypeManager(self.context).listTypes(('resource',))])
def resourceTypesForSearch(self):
general = [('loops:resource:*', 'Any'),]
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
for t in ITypeManager(self.context).listTypes(('resource',))])
def predicates(self): def predicates(self):
preds = PredicateSourceList(self.context) preds = PredicateSourceList(self.context)
terms = zapi.getMultiAdapter((preds, self.request), ITerms) terms = zapi.getMultiAdapter((preds, self.request), ITerms)

View file

@ -303,7 +303,7 @@
/> />
<page <page
for="loops.interfaces.IDocument" for="loops.interfaces.IResource"
name="document.html" name="document.html"
permission="zope.View" permission="zope.View"
template="document.pt" template="document.pt"
@ -566,6 +566,20 @@
permission="zope.ManageContent" permission="zope.ManageContent"
/> />
<page
name="edit_object.html"
for="loops.interfaces.INode"
class="loops.browser.form.EditObjectForm"
permission="zope.ManageContent"
/>
<page
name="inner_form.html"
for="loops.interfaces.INode"
class="loops.browser.form.InnerForm"
permission="zope.ManageContent"
/>
<zope:adapter <zope:adapter
name="create_resource" name="create_resource"
for="loops.browser.node.NodeView for="loops.browser.node.NodeView
@ -574,6 +588,14 @@
permission="zope.ManageContent" permission="zope.ManageContent"
/> />
<zope:adapter
name="edit_resource"
for="loops.browser.node.NodeView
zope.publisher.interfaces.browser.IBrowserRequest"
factory="loops.browser.form.EditObject"
permission="zope.ManageContent"
/>
<zope:adapter factory="loops.browser.form.ResourceNameChooser" /> <zope:adapter factory="loops.browser.form.ResourceNameChooser" />
<!-- inner HTML views --> <!-- inner HTML views -->

View file

@ -31,36 +31,26 @@ from zope.app.container.interfaces import INameChooser
from zope.app.container.contained import NameChooser 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, EditForm, FormFields
from zope.publisher.interfaces import BadRequest from zope.publisher.interfaces import BadRequest
from cybertools.ajax import innerHtml from cybertools.ajax import innerHtml
from cybertools.browser.form import FormController from cybertools.browser.form import FormController
from cybertools.typology.interfaces import IType from cybertools.typology.interfaces import IType
from loops.interfaces import IResourceManager from loops.interfaces import IResourceManager, INote
from loops.browser.node import NodeView from loops.browser.node import NodeView
from loops.resource import Resource from loops.resource import Resource
from loops.type import ITypeConcept
from loops import util from loops import util
from loops.util import _ from loops.util import _
class CreateObjectForm(NodeView, Form):
class ObjectForm(NodeView):
template = ViewPageTemplateFile('form_macros.pt') 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__='data', 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): def __init__(self, context, request):
super(CreateObjectForm, self).__init__(context, request) super(ObjectForm, self).__init__(context, request)
def setUp(self): def setUp(self):
self.setUpWidgets() self.setUpWidgets()
@ -70,6 +60,52 @@ class CreateObjectForm(NodeView, Form):
return innerHtml(self) return innerHtml(self)
class CreateObjectForm(ObjectForm, Form):
@property
def macro(self): return self.template.macros['create']
title = _(u'Create Resource, Type = ')
form_action = 'create_resource'
@property
def form_fields(self):
typeToken = self.request.get('form.type')
if typeToken:
t = self.loopsRoot.loopsTraverse(typeToken)
ifc = ITypeConcept(t).typeInterface
else:
ifc = INote
return FormFields(ifc)
class EditObjectForm(ObjectForm, EditForm):
@property
def macro(self): return self.template.macros['edit']
title = _(u'Edit Resource')
form_action = 'edit_resource'
@Lazy
def typeInterface(self):
return IType(self.context).typeInterface
@property
def form_fields(self):
return FormFields(self.typeInterface)
def __init__(self, context, request):
super(EditObjectForm, self).__init__(context, request)
self.context = self.virtualTargetObject
class InnerForm(ObjectForm):
@property
def macro(self): return self.template.macros['fields']
class CreateObject(FormController): class CreateObject(FormController):
@Lazy @Lazy
@ -87,12 +123,13 @@ class CreateObject(FormController):
raise BadRequest('Title field is empty') raise BadRequest('Title field is empty')
name = INameChooser(container).chooseName(title, obj) name = INameChooser(container).chooseName(title, obj)
container[name] = obj container[name] = obj
obj.resourceType = self.loopsRoot.getConceptManager()['note'] tc = form.get('form.type') or '.loops/concepts/note'
obj.resourceType = self.loopsRoot.loopsTraverse(tc)
adapter = IType(obj).typeInterface(obj) 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',): if fn in ('action', 'type',) or fn.endswith('-empty-marker'):
continue continue
value = form[k] value = form[k]
if fn.startswith(conceptPrefix): if fn.startswith(conceptPrefix):
@ -104,7 +141,7 @@ class CreateObject(FormController):
return True return True
def assignConcepts(self, obj, fieldName, value): def assignConcepts(self, obj, fieldName, value):
if fieldName == 'search.text_selected': if value and fieldName == 'search.text_selected':
concept = util.getObjectForUid(value) concept = util.getObjectForUid(value)
obj.assignConcept(concept) obj.assignConcept(concept)
@ -117,3 +154,36 @@ class ResourceNameChooser(NameChooser):
name = title.replace(' ', '_').lower() name = title.replace(' ', '_').lower()
name = super(ResourceNameChooser, self).chooseName(name, obj) name = super(ResourceNameChooser, self).chooseName(name, obj)
return name return name
class EditObject(FormController):
@Lazy
def loopsRoot(self):
return self.view.loopsRoot
def update(self):
prefix = 'form.'
conceptPrefix = 'concept.'
form = self.request.form
obj = self.view.virtualTargetObject
adapter = IType(obj).typeInterface(obj)
for k in form.keys():
if k.startswith(prefix):
fn = k[len(prefix):]
if fn in ('action', 'type',) or fn.endswith('-empty-marker'):
continue
value = form[k]
if fn.startswith(conceptPrefix):
self.assignConcepts(obj, fn[len(conceptPrefix):], value)
else:
setattr(adapter, fn, value)
notify(ObjectModifiedEvent(obj))
return True
def assignConcepts(self, obj, fieldName, value):
if value and fieldName == 'search.text_selected':
concept = util.getObjectForUid(value)
obj.assignConcept(concept)

View file

@ -1,16 +1,82 @@
<metal:block define-macro="edit">
<form method="post">
<input type="hidden" name="form.action" value="edit"
tal:attributes="value view/form_action" />
<table cellpadding="3" class="form">
<tbody>
<tr>
<th colspan="4">
<br />
<span tal:replace="view/title"
i18n:translate="">Edit Information Object
</span>
</th>
</tr>
</tbody>
<tbody id="form.fields">
<metal:fields use-macro="view/template/macros/fields" />
</tbody>
<tbody>
<tr>
<td colspan="4" class="headline">Assign Concept(s)</td>
</tr>
<tr metal:use-macro="view/template/macros/search_concepts" />
<tr metal:use-macro="view/template/macros/buttons" />
</tbody>
</table>
</form>
</metal:block>
<metal:block define-macro="create"> <metal:block define-macro="create">
<div tal:define="dummy view/setUp">
<form method="post"> <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">
<tbody>
<tr> <tr>
<th colspan="4"> <th colspan="4">
<br />
<span tal:replace="view/title" <span tal:replace="view/title"
i18n:translate="">Create Information Object</span> i18n:translate="">Create Information Object</span>
<select name="form.type" id="form.type"
tal:attributes="onChange
string:return replaceFieldsNode(
'form.fields', 'form.type', 'inner_form.html')">
<option value=".loops/concepts/note"
tal:repeat="type view/resourceTypes"
tal:content="type/title"
tal:attributes="value type/token;
selected python:
type.token == (request.get('form.type')
or '.loops/concepts/note')">
Note
</option>
</select>
</th> </th>
</tr> </tr>
</tbody>
<tbody id="form.fields">
<metal:fields use-macro="view/template/macros/fields" />
</tbody>
<tbody>
<tr>
<td colspan="4" class="headline">Assign Concept(s)</td>
</tr>
<tr metal:use-macro="view/template/macros/search_concepts" />
<tr metal:use-macro="view/template/macros/buttons" />
</tbody>
</table>
</form>
</metal:block>
<metal:fields define-macro="fields">
<tal:block tal:define="dummy view/setUp">
<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">
@ -31,11 +97,11 @@
</div> </div>
</td> </td>
</tr> </tr>
</tal:block>
</metal:fields>
<tr>
<td colspan="4" class="headline">Assign Concept(s)</td> <tr metal:define-macro="search_concepts">
</tr>
<tr>
<td><label for="form.concept.search.type">Type:</label></td> <td><label for="form.concept.search.type">Type:</label></td>
<td> <td>
<select name="form.concept.search.type" id="form.concept.search.type" <select name="form.concept.search.type" id="form.concept.search.type"
@ -58,15 +124,13 @@
string:${context/@@absolute_url}/listConceptsForComboBox.js?searchString=%{searchString}&searchType=" /> string:${context/@@absolute_url}/listConceptsForComboBox.js?searchString=%{searchString}&searchType=" />
</td> </td>
</tr> </tr>
<tr>
<tr metal:define-macro="buttons">
<td colspan="4"> <td colspan="4">
<input type="button" value="Cancel" <input type="button" value="Cancel"
onclick="createObjectDlg.hide()"> onclick="objectDlg.hide()">
<input type="submit" value="Save" <input type="submit" value="Save"
onclick="createObjectDlg.hide()"> onclick="objectDlg.hide()">
</td> </td>
</tr> </tr>
</table>
</form>
</div>
</metal:block>

View file

@ -13,9 +13,12 @@ function focusOpener() {
} }
} }
/*function listConceptsForComboBox() { function replaceFieldsNode(targetId, typeId, url) {
return [['Zope', 'zope'], ] token = dojo.byId(typeId).value;
}*/ dojo.io.updateNode(targetId, {
url: url + '?form.type=' + token,
});
}
function submitReplacing(targetId, formId, actionUrl) { function submitReplacing(targetId, formId, actionUrl) {
dojo.io.updateNode(targetId, { dojo.io.updateNode(targetId, {
@ -54,19 +57,17 @@ function setConceptTypeForComboBox(typeId, cbId) {
dp.searchUrl = newUrl; dp.searchUrl = newUrl;
} }
var createObjectDlg = false; var objectDlg = false;
function createObjectDialog() { function objectDialog(url) {
//createObjectDlg = dojo.widget.byId('createObject');
//createObjectDlg = false;
dojo.require('dojo.widget.Dialog'); dojo.require('dojo.widget.Dialog');
dojo.require('dojo.widget.ComboBox'); dojo.require('dojo.widget.ComboBox');
if (!createObjectDlg) { if (!objectDlg) {
createObjectDlg = dojo.widget.fromScript('Dialog', objectDlg = dojo.widget.fromScript('Dialog',
{bgColor: 'white', bgOpacity: 0.5, toggle: 'fade', toggleDuration: 250, {bgColor: 'white', bgOpacity: 0.5, toggle: 'fade', toggleDuration: 250,
executeScripts: true, executeScripts: true,
href: 'create_object.html' href: url
}, dojo.byId('createObject')); }, dojo.byId('objectDialog'));
} }
createObjectDlg.show(); objectDlg.show();
} }

View file

@ -206,13 +206,16 @@
<metal:actions define-macro="actions"> <metal:actions define-macro="actions">
<div class="menu-2" <div class="menu-2"
tal:define="dummy view/registerDojo"> tal:define="dummy view/registerDojo">
<a href="javascript:createObjectDialog()" <a href="#"
onclick="createObjectDialog(); return false;"> onclick="objectDialog('create_object.html'); return false;">
Create Resource... Create Resource...
</a><br />
<a href="#"
onclick="objectDialog('edit_object.html'); return false;">
Edit Resource...
</a> </a>
<span id="createObject">
</span>
</div> </div>
<span id="objectDialog"></span>
</metal:actions> </metal:actions>

View file

@ -72,7 +72,7 @@ class IConcept(ILoopsObject, IPotentialTarget):
title=_(u'Title'), title=_(u'Title'),
description=_(u'Title of the concept'), description=_(u'Title of the concept'),
default=u'', default=u'',
required=False) required=True)
conceptType = schema.Choice( conceptType = schema.Choice(
title=_(u'Concept Type'), title=_(u'Concept Type'),
@ -190,7 +190,7 @@ class IBaseResource(ILoopsObject):
description=_(u'Title of the resource'), description=_(u'Title of the resource'),
default=u'', default=u'',
missing_value=u'', missing_value=u'',
required=False) required=True)
resourceType = schema.Choice( resourceType = schema.Choice(
title=_(u'Resource Type'), title=_(u'Resource Type'),
@ -228,7 +228,7 @@ class IResourceSchema(Interface):
description=_(u'Title of the resource'), description=_(u'Title of the resource'),
default=u'', default=u'',
missing_value=u'', missing_value=u'',
required=False) required=True)
data = schema.Bytes( data = schema.Bytes(
title=_(u'Data'), title=_(u'Data'),
@ -549,7 +549,7 @@ class IResourceAdapter(IBaseResourceSchema):
""" """
class IFile(IResourceAdapter): class IFile(IResourceAdapter, IResourceSchema):
""" A media asset that is not shown on a (web) page like an image but """ A media asset that is not shown on a (web) page like an image but
may be downloaded instead. may be downloaded instead.
""" """

View file

@ -194,6 +194,15 @@ class FileAdapter(ResourceAdapterBase):
""" """
implements(IFile) implements(IFile)
_schemas = list(IFile) + list(IBaseResource)
class TextDocumentAdapter(ResourceAdapterBase):
""" A type adapter for providing text document functionality for resources.
"""
implements(IDocument)
_schemas = list(IDocument) + list(IBaseResource)
class NoteAdapter(ResourceAdapterBase): class NoteAdapter(ResourceAdapterBase):
@ -203,13 +212,11 @@ class NoteAdapter(ResourceAdapterBase):
implements(INote) implements(INote)
_schemas = list(INote) + list(IBaseResource) _schemas = list(INote) + list(IBaseResource)
#contentType = u'text/restructured'
class DocumentWriteFileAdapter(object): class DocumentWriteFileAdapter(object):
implements(IWriteFile) implements(IWriteFile)
adapts(IDocument) adapts(IResource)
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context
@ -222,7 +229,7 @@ class DocumentWriteFileAdapter(object):
class DocumentReadFileAdapter(object): class DocumentReadFileAdapter(object):
implements(IReadFile) implements(IReadFile)
adapts(IDocument) adapts(IResource)
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context