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:
		
							parent
							
								
									87cb629f1c
								
							
						
					
					
						commit
						40b8182f06
					
				
					 9 changed files with 118 additions and 31 deletions
				
			
		|  | @ -603,16 +603,14 @@ | ||||||
|       for="loops.browser.node.NodeView |       for="loops.browser.node.NodeView | ||||||
|            zope.publisher.interfaces.browser.IBrowserRequest" |            zope.publisher.interfaces.browser.IBrowserRequest" | ||||||
|       factory="loops.browser.form.CreateConcept" |       factory="loops.browser.form.CreateConcept" | ||||||
|       permission="zope.ManageContent" |       permission="zope.ManageContent" /> | ||||||
|       /> |  | ||||||
| 
 | 
 | ||||||
|   <zope:adapter |   <zope:adapter | ||||||
|       name="edit_concept" |       name="edit_concept" | ||||||
|       for="loops.browser.node.NodeView |       for="loops.browser.node.NodeView | ||||||
|            zope.publisher.interfaces.browser.IBrowserRequest" |            zope.publisher.interfaces.browser.IBrowserRequest" | ||||||
|       factory="loops.browser.form.EditConcept" |       factory="loops.browser.form.EditConcept" | ||||||
|       permission="zope.ManageContent" |       permission="zope.ManageContent" /> | ||||||
|       /> |  | ||||||
| 
 | 
 | ||||||
|   <!-- inner HTML views --> |   <!-- inner HTML views --> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | #  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 | #  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_html'] = self.template.macros['input_html'] | ||||||
|         renderers['input_grid'] = grid_macros.macros['input_grid'] |         renderers['input_grid'] = grid_macros.macros['input_grid'] | ||||||
|         renderers['input_relationset'] = relation_macros.macros['input_relationset'] |         renderers['input_relationset'] = relation_macros.macros['input_relationset'] | ||||||
|  |         renderers['input_relation'] = relation_macros.macros['input_relation'] | ||||||
|         return renderers |         return renderers | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|  | @ -397,8 +398,7 @@ class CreateConceptPage(CreateConceptForm): | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|     def nextUrl(self): |     def nextUrl(self): | ||||||
|         #return self.nodeView.getUrlForTarget(self.context) |         return self.getUrlForTarget(self.virtualTargetObject) | ||||||
|         return self.getUrlForTarget(self.context) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class InnerForm(CreateObjectForm): | class InnerForm(CreateObjectForm): | ||||||
|  |  | ||||||
|  | @ -189,8 +189,6 @@ | ||||||
| </metal:assignments> | </metal:assignments> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| <metal:versioning define-macro="versioning" | <metal:versioning define-macro="versioning" | ||||||
|                   tal:define="versionInfo view/versionInfo" |                   tal:define="versionInfo view/versionInfo" | ||||||
|                   tal:condition="versionInfo"> |                   tal:condition="versionInfo"> | ||||||
|  |  | ||||||
|  | @ -147,11 +147,26 @@ function addRelation(fieldName) { | ||||||
|     valuesNode = dojo.byId(fieldName + '_values'); |     valuesNode = dojo.byId(fieldName + '_values'); | ||||||
|     widget = dijit.byId(fieldName + '_search'); |     widget = dijit.byId(fieldName + '_search'); | ||||||
|     token = widget.getValue(); |     token = widget.getValue(); | ||||||
|  |     if (token) { | ||||||
|         title = widget.getDisplayedValue(); |         title = widget.getDisplayedValue(); | ||||||
|     ih = '<input type="checkbox" name="' + name + ':list" value="' + token + '" checked> <span>' + title + '</span>'; |         ih = '<div><input type="checkbox" name="' + fieldName + ':list" value="' + token + '" checked> <span>' + title + '</span></div>'; | ||||||
|         newNode = document.createElement('div'); |         newNode = document.createElement('div'); | ||||||
|         newNode.innerHTML = ih; |         newNode.innerHTML = ih; | ||||||
|         valuesNode.appendChild(newNode); |         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() { | function validate() { | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								common.py
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								common.py
									
										
									
									
									
								
							|  | @ -387,6 +387,16 @@ class RelationSetProperty(object): | ||||||
|             return self |             return self | ||||||
|         return self.factory(inst, self.predicateName) |         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): | class ParentRelationSetProperty(RelationSetProperty): | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -345,6 +345,8 @@ | ||||||
|            name="grid" /> |            name="grid" /> | ||||||
|   <adapter factory="loops.schema.field.RelationSetFieldInstance" |   <adapter factory="loops.schema.field.RelationSetFieldInstance" | ||||||
|            name="relationset" /> |            name="relationset" /> | ||||||
|  |   <adapter factory="loops.schema.field.RelationFieldInstance" | ||||||
|  |            name="relation" /> | ||||||
| 
 | 
 | ||||||
|   <adapter factory="cybertools.composer.schema.factory.SchemaFactory" /> |   <adapter factory="cybertools.composer.schema.factory.SchemaFactory" /> | ||||||
|   <adapter factory="loops.schema.factory.ResourceSchemaFactory" /> |   <adapter factory="loops.schema.factory.ResourceSchemaFactory" /> | ||||||
|  |  | ||||||
|  | @ -24,13 +24,13 @@ $Id$ | ||||||
| 
 | 
 | ||||||
| from zope.component import adapts | from zope.component import adapts | ||||||
| from zope.interface import Attribute, implements | from zope.interface import Attribute, implements | ||||||
| from zope.schema import Choice, List | from zope.schema import Field, List | ||||||
| from zope.schema.interfaces import IChoice, IList | from zope.schema.interfaces import IField, IList | ||||||
| 
 | 
 | ||||||
| from cybertools.composer.schema.interfaces import FieldType | from cybertools.composer.schema.interfaces import FieldType | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class IRelation(IChoice): | class IRelation(IField): | ||||||
|     """ An object addressed via a single relation. |     """ An object addressed via a single relation. | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|  | @ -50,11 +50,14 @@ class IRelationSet(IList): | ||||||
|                 'targets for the relations.') |                 'targets for the relations.') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Relation(Choice): | class Relation(Field): | ||||||
| 
 | 
 | ||||||
|     implements(IRelation) |     implements(IRelation) | ||||||
| 
 | 
 | ||||||
|     __typeInfo__ = ('relation',) |     __typeInfo__ = ('relation', | ||||||
|  |                     FieldType('relation', 'relation', | ||||||
|  |                               u'A field representing a related object.', | ||||||
|  |                               instanceName='relation')) | ||||||
| 
 | 
 | ||||||
|     def __init__(self, *args, **kw): |     def __init__(self, *args, **kw): | ||||||
|         self.target_types = kw.pop('target_types') |         self.target_types = kw.pop('target_types') | ||||||
|  |  | ||||||
|  | @ -28,9 +28,10 @@ from zope.interface import implements | ||||||
| from zope.app.pagetemplate import ViewPageTemplateFile | from zope.app.pagetemplate import ViewPageTemplateFile | ||||||
| from zope.cachedescriptors.property import Lazy | from zope.cachedescriptors.property import Lazy | ||||||
| import zope.schema | import zope.schema | ||||||
|  | from zope.traversing.api import getName | ||||||
| 
 | 
 | ||||||
| from cybertools.composer.schema.factory import createField | 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 IField, IFieldInstance | ||||||
| from cybertools.composer.schema.interfaces import fieldTypes, undefined | from cybertools.composer.schema.interfaces import fieldTypes, undefined | ||||||
| from cybertools.util.format import toStr, toUnicode | from cybertools.util.format import toStr, toUnicode | ||||||
|  | @ -41,17 +42,7 @@ from loops import util | ||||||
| relation_macros = ViewPageTemplateFile('relation_macros.pt') | relation_macros = ViewPageTemplateFile('relation_macros.pt') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RelationSetFieldInstance(ListFieldInstance): | class BaseRelationFieldInstance(object): | ||||||
| 
 |  | ||||||
|     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 |  | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|     def typesParams(self): |     def typesParams(self): | ||||||
|  | @ -62,3 +53,40 @@ class RelationSetFieldInstance(ListFieldInstance): | ||||||
|         if result: |         if result: | ||||||
|             return '?' + '&'.join(result) |             return '?' + '&'.join(result) | ||||||
|         return '' |         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) | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -17,6 +17,13 @@ | ||||||
|                                value obj/uid" /> |                                value obj/uid" /> | ||||||
|         <span tal:content="obj/title" /> |         <span tal:content="obj/title" /> | ||||||
|       </div> |       </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> |     </div> | ||||||
|     <input dojoType="dijit.form.FilteringSelect" |     <input dojoType="dijit.form.FilteringSelect" | ||||||
|            autoComplete="False" labelAttr="label" |            autoComplete="False" labelAttr="label" | ||||||
|  | @ -27,5 +34,31 @@ | ||||||
| </metal:textline> | </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> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 helmutm
						helmutm