diff --git a/README.txt b/README.txt index b2df97d..8e47af5 100755 --- a/README.txt +++ b/README.txt @@ -608,6 +608,45 @@ Creating an object >>> from loops.browser.form import CreateObjectForm, CreateObject >>> form = CreateObjectForm(m112, TestRequest()) +The form provides a set of data entry fields derived from the interface +associated with the new object's resource (or concept) type. + +In addition it allows to assign concepts as parents to the object. Beside +an integrated free search for concepts to assign there may be a list of +preset concepts, e.g. depending on the target of the current node: + + >>> form.assignments + () + >>> m112.target = cc1 + >>> form = CreateObjectForm(m112, TestRequest()) + >>> form.assignments + (<...ConceptRelationView object ...>,) + +There also may be preset concept types that directly provide lists of +concepts to select from. + +To show this let's start with a new type, the customer type. + + >>> customer = concepts['customer'] = Concept('Customer') + >>> customer.conceptType = concepts.getTypeConcept() + >>> from loops.type import ConceptType, TypeConcept + >>> custType = TypeConcept(customer) + >>> custType.options + [] + >>> cust1 = concepts['cust1'] = Concept(u'Zope Corporation') + >>> cust2 = concepts['cust2'] = Concept(u'cyberconcepts') + >>> for c in (cust1, cust2): c.conceptType = customer + >>> custType.options = ('qualifier:assign',) + >>> ConceptType(cust1).qualifiers + ('concept', 'assign') + + >>> form = CreateObjectForm(m112, TestRequest()) + >>> form.presetTypesForAssignment + [{'token': 'loops:concept:customer', 'title': 'Customer'}] + +OK, so much about the form - now we want to create a new object based +on data provided in this form: + >>> from loops.interfaces import INote, ITypeConcept >>> from loops.type import TypeConcept >>> from loops.resource import NoteAdapter @@ -708,7 +747,7 @@ target object's view here: [] >>> action = view.virtualTarget.getActions()[0] >>> action.url - 'http://127.0.0.1/loops/views/m1/m11/m111/.target16' + 'http://127.0.0.1/loops/views/m1/m11/m111/.target19' Import/Export diff --git a/browser/form.py b/browser/form.py index 444b57a..4b0790c 100644 --- a/browser/form.py +++ b/browser/form.py @@ -40,12 +40,13 @@ from zope.security.proxy import isinstance from cybertools.ajax import innerHtml from cybertools.browser.form import FormController -from cybertools.typology.interfaces import IType +from cybertools.typology.interfaces import IType, ITypeManager from loops.concept import ResourceRelation from loops.interfaces import IConcept, IResourceManager, IDocument from loops.interfaces import IFile, IExternalFile, INote from loops.browser.node import NodeView from loops.browser.concept import ConceptRelationView +from loops.query import ConceptQuery from loops.resource import Resource from loops.type import ITypeConcept from loops import util @@ -98,8 +99,27 @@ class ObjectForm(NodeView): @Lazy def defaultPredicate(self): - return util.getUidForObject( - self.loopsRoot.getConceptManager().getDefaultPredicate()) + return self.loopsRoot.getConceptManager().getDefaultPredicate() + + @Lazy + def typeManager(self): + return ITypeManager(self.context) + + @Lazy + def presetTypesForAssignment(self): + types = list(self.typeManager.listTypes(include=('assign',))) + assigned = [r.context.conceptType for r in self.assignments] + types = [t for t in types if t.typeProvider not in assigned] + return [dict(title=t.title, token=t.tokenForSearch) for t in types] + + def conceptsForType(self, token): + noSelection = dict(token='none', title=u'not selected') + result = sorted(ConceptQuery(self).query(type=token), key=lambda x: x.title) + predicateUid = util.getUidForObject(self.defaultPredicate) + return ([noSelection] + + [dict(title=o.title, + token='%s:%s' % (util.getUidForObject(o), predicateUid)) + for o in result]) class WidgetController(object): @@ -241,6 +261,9 @@ class EditObject(FormController): if fn.startswith(self.conceptPrefix) and value: self.collectConcepts(fn[len(self.conceptPrefix):], value) else: + if not value and fn == 'data' and IFile.providedBy(adapted): + # empty file data - don' change + continue if isinstance(value, FileUpload): filename = getattr(value, 'filename', '') value = value.read() @@ -273,7 +296,7 @@ class EditObject(FormController): predicate = util.getObjectForUid(p) obj.deassignConcept(concept, [predicate]) for v in self.selected: - if v not in self.old: + if v != 'none' and v not in self.old: c, p = v.split(':') concept = util.getObjectForUid(c) predicate = util.getObjectForUid(p) diff --git a/browser/form_macros.pt b/browser/form_macros.pt index 114e1fb..e1145be 100644 --- a/browser/form_macros.pt +++ b/browser/form_macros.pt @@ -105,6 +105,19 @@ + + Type: + + Select value: + + + +