provide implementation for relation set and relation field types

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3184 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2009-01-27 16:35:05 +00:00
parent 87cb629f1c
commit 40b8182f06
9 changed files with 118 additions and 31 deletions

View file

@ -603,16 +603,14 @@
for="loops.browser.node.NodeView
zope.publisher.interfaces.browser.IBrowserRequest"
factory="loops.browser.form.CreateConcept"
permission="zope.ManageContent"
/>
permission="zope.ManageContent" />
<zope:adapter
name="edit_concept"
for="loops.browser.node.NodeView
zope.publisher.interfaces.browser.IBrowserRequest"
factory="loops.browser.form.EditConcept"
permission="zope.ManageContent"
/>
permission="zope.ManageContent" />
<!-- inner HTML views -->

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
# Copyright (c) 2009 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
@ -115,6 +115,7 @@ class ObjectForm(NodeView):
renderers['input_html'] = self.template.macros['input_html']
renderers['input_grid'] = grid_macros.macros['input_grid']
renderers['input_relationset'] = relation_macros.macros['input_relationset']
renderers['input_relation'] = relation_macros.macros['input_relation']
return renderers
@Lazy
@ -397,8 +398,7 @@ class CreateConceptPage(CreateConceptForm):
@Lazy
def nextUrl(self):
#return self.nodeView.getUrlForTarget(self.context)
return self.getUrlForTarget(self.context)
return self.getUrlForTarget(self.virtualTargetObject)
class InnerForm(CreateObjectForm):

View file

@ -189,8 +189,6 @@
</metal:assignments>
<metal:versioning define-macro="versioning"
tal:define="versionInfo view/versionInfo"
tal:condition="versionInfo">

View file

@ -147,11 +147,26 @@ function addRelation(fieldName) {
valuesNode = dojo.byId(fieldName + '_values');
widget = dijit.byId(fieldName + '_search');
token = widget.getValue();
title = widget.getDisplayedValue();
ih = '<input type="checkbox" name="' + name + ':list" value="' + token + '" checked> <span>' + title + '</span>';
newNode = document.createElement('div');
newNode.innerHTML = ih;
valuesNode.appendChild(newNode);
if (token) {
title = widget.getDisplayedValue();
ih = '<div><input type="checkbox" name="' + fieldName + ':list" value="' + token + '" checked> <span>' + title + '</span></div>';
newNode = document.createElement('div');
newNode.innerHTML = ih;
valuesNode.appendChild(newNode);
}
}
function setRelation(fieldName) {
valuesNode = dojo.byId(fieldName + '_values');
widget = dijit.byId(fieldName + '_search');
token = widget.getValue();
if (token) {
title = widget.getDisplayedValue();
ih = '<div><input type="checkbox" name="' + fieldName + '" value="' + token + '" checked> <span>' + title + '</span></div>';
newNode = document.createElement('div');
newNode.innerHTML = ih;
valuesNode.replaceChild(newNode, valuesNode.firstChild);
}
}
function validate() {

View file

@ -387,6 +387,16 @@ class RelationSetProperty(object):
return self
return self.factory(inst, self.predicateName)
def __set__(self, inst, value):
rs = self.factory(inst, self.predicateName)
current = list(rs)
for c in current:
if c not in value:
rs.remove(c)
for v in value:
if v not in current:
rs.add(v)
class ParentRelationSetProperty(RelationSetProperty):

View file

@ -345,6 +345,8 @@
name="grid" />
<adapter factory="loops.schema.field.RelationSetFieldInstance"
name="relationset" />
<adapter factory="loops.schema.field.RelationFieldInstance"
name="relation" />
<adapter factory="cybertools.composer.schema.factory.SchemaFactory" />
<adapter factory="loops.schema.factory.ResourceSchemaFactory" />

View file

@ -24,13 +24,13 @@ $Id$
from zope.component import adapts
from zope.interface import Attribute, implements
from zope.schema import Choice, List
from zope.schema.interfaces import IChoice, IList
from zope.schema import Field, List
from zope.schema.interfaces import IField, IList
from cybertools.composer.schema.interfaces import FieldType
class IRelation(IChoice):
class IRelation(IField):
""" An object addressed via a single relation.
"""
@ -50,11 +50,14 @@ class IRelationSet(IList):
'targets for the relations.')
class Relation(Choice):
class Relation(Field):
implements(IRelation)
__typeInfo__ = ('relation',)
__typeInfo__ = ('relation',
FieldType('relation', 'relation',
u'A field representing a related object.',
instanceName='relation'))
def __init__(self, *args, **kw):
self.target_types = kw.pop('target_types')

View file

@ -28,9 +28,10 @@ from zope.interface import implements
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
import zope.schema
from zope.traversing.api import getName
from cybertools.composer.schema.factory import createField
from cybertools.composer.schema.field import ListFieldInstance
from cybertools.composer.schema.field import FieldInstance, ListFieldInstance
from cybertools.composer.schema.interfaces import IField, IFieldInstance
from cybertools.composer.schema.interfaces import fieldTypes, undefined
from cybertools.util.format import toStr, toUnicode
@ -41,17 +42,7 @@ from loops import util
relation_macros = ViewPageTemplateFile('relation_macros.pt')
class RelationSetFieldInstance(ListFieldInstance):
def marshall(self, value):
return [dict(title=v.title, uid=util.getUidForObject(v.context))
for v in value]
def display(self, value):
return value
def unmarshall(self, value):
return value
class BaseRelationFieldInstance(object):
@Lazy
def typesParams(self):
@ -62,3 +53,40 @@ class RelationSetFieldInstance(ListFieldInstance):
if result:
return '?' + '&'.join(result)
return ''
def getPresetTargets(self, view):
if view.adapted.__is_dummy__:
# only for object in creation
target = view.virtualTargetObject
if getName(target.conceptType) in self.context.target_types:
return [dict(title=target.title, uid=util.getUidForObject(target))]
return []
class RelationSetFieldInstance(ListFieldInstance, BaseRelationFieldInstance):
def marshall(self, value):
return [dict(title=v.title, uid=util.getUidForObject(v.context))
for v in value]
def display(self, value):
return ' | '.join([v.title for v in value])
def unmarshall(self, value):
return [util.getObjectForUid(v) for v in value]
class RelationFieldInstance(FieldInstance, BaseRelationFieldInstance):
def marshall(self, value):
if value:
return dict(title=value.title, uid=util.getUidForObject(value))
def display(self, value):
if value:
return value.title
return u''
def unmarshall(self, value):
return util.getObjectForUid(value)

View file

@ -17,6 +17,13 @@
value obj/uid" />
<span tal:content="obj/title" />
</div>
<div tal:repeat="obj python:
fieldInstance.getPresetTargets(view)">
<input type="checkbox" checked
tal:attributes="name string:$name:list;
value obj/uid" />
<span tal:content="obj/title" />
</div>
</div>
<input dojoType="dijit.form.FilteringSelect"
autoComplete="False" labelAttr="label"
@ -27,5 +34,31 @@
</metal:textline>
<metal:textline define-macro="input_relation"
tal:define="fieldInstance field/getFieldInstance;
types fieldInstance/typesParams">
<div dojoType="dojox.data.QueryReadStore" jsId="conceptSearch"
tal:attributes="url string:listConceptsForComboBox.js$types;
jsId string:${name}_search_store" >
</div>
<div tal:define="obj data/?name"
tal:attributes="id string:${name}_values"><div>
<tal:block tal:condition="obj">
<input type="checkbox" checked
tal:attributes="name string:$name;
value obj/uid" />
<span tal:content="obj/title" />
</tal:block>
</div>
</div>
<input dojoType="dijit.form.FilteringSelect"
autoComplete="False" labelAttr="label"
tal:attributes="store string:${name}_search_store;
name string:${name}_search;
id string:${name}_search;
onChange string:setRelation('$name')" />
</metal:textline>
</body>
</html>