diff --git a/README.txt b/README.txt index 78cfeac..5e7c678 100755 --- a/README.txt +++ b/README.txt @@ -561,6 +561,48 @@ cybertools.relation package.) >>> IMediaAssetView.providedBy(m111) False +Target views +------------ + +We can directly retrieve a target's view by using the NodeView's +``targetObjectView`` property. If the target is a concept we get a ConceptView +that provides methods e.g. for retrieving the concept's relations. +These are again wrapped as views, i.e. as instances of the +ConceptRelationView class. + + >>> from loops.interfaces import IConcept + >>> component.provideAdapter(ConceptView, (IConcept, IBrowserRequest), Interface) + + >>> m112.target = cc1 + >>> view = NodeView(m112, TestRequest()) + >>> childRels = list(view.targetObjectView.children()) + >>> childRels[0] + + +A fairly useful method for providing links to target objects of a node +is ``NodeView.getUrlForTarget()`` that expects a ConceptView, ResourceView, +or ConceptRelationView as its argument. + + >>> view.getUrlForTarget(childRels[0]) + 'http://127.0.0.1/loops/views/m1/m11/m112/.target39' + +Actions +------- + + >>> from cybertools.browser.liquid.controller import Controller + >>> request = TestRequest() + >>> view = NodeView(m112, request) + >>> view.controller = Controller(view, request) + >>> view.setupController() + + >>> actions = view.getActions('portlet') + >>> len(actions) + 1 + +Clean-up: + + >>> m112.target = None + Ordering Nodes -------------- @@ -761,11 +803,10 @@ In order to provide suitable links for viewing or editing a target you may ask a view which view and edit actions it supports. We directly use the target object's view here: - >>> view.virtualTarget.getActions() - [] - >>> action = view.virtualTarget.getActions()[0] - >>> action.url - 'http://127.0.0.1/loops/views/m1/m11/m111/.target23' + >>> actions = view.virtualTarget.getActions('object', page=view) + >>> #actions[0].url + +'http://127.0.0.1/loops/views/m1/m11/m111/.target23' Collecting Information about Parents diff --git a/browser/action.py b/browser/action.py new file mode 100644 index 0000000..3d8b5ff --- /dev/null +++ b/browser/action.py @@ -0,0 +1,66 @@ +# +# Copyright (c) 2007 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Base classes (sort of views) for action portlet items. + +$Id$ +""" + +from zope import component +from zope.app.pagetemplate import ViewPageTemplateFile +from zope.cachedescriptors.property import Lazy + +action_macros = ViewPageTemplateFile('action_macros.pt') + + +class Action(object): + + template = action_macros + macroName = 'action' + condition = True + permission = None + url = '.' + targetWindow = '' + title = '' + description = '' + icon = '' + cssClass = '' + onClick = '' + innerHtmlId = '' + + def __init__(self, view, **kw): + self.view = view + for k, v in kw.items(): + setattr(self, k, v) + + @Lazy + def macro(self): + return self.template.macros[self.macroName] + + @Lazy + def url(self): + return self.view.url + + +class TargetAction(object): + + @Lazy + def url(self): + return self.view.virtualTargetUrl + diff --git a/browser/action_macros.pt b/browser/action_macros.pt new file mode 100644 index 0000000..2fb2e38 --- /dev/null +++ b/browser/action_macros.pt @@ -0,0 +1,23 @@ + + + +
+ iconAction Title + +
+ +
diff --git a/browser/common.py b/browser/common.py index 019769c..a3e2145 100644 --- a/browser/common.py +++ b/browser/common.py @@ -97,6 +97,8 @@ class EditForm(form.EditForm): class BaseView(GenericView): + actions = {} # default only, don't update + def __init__(self, context, request): super(BaseView, self).__init__(context, request) # TODO: get rid of removeSecurityProxy() call @@ -329,11 +331,14 @@ class BaseView(GenericView): def editable(self): return canWrite(self.context, 'title') - def getActions(self, category): + def getActions(self, category='object', page=None): """ Return a list of actions that provide the view and edit actions available for the context object. """ - return [] + actions = [] + if category in self.actions: + actions.extend(self.actions[category](self, page=page)) + return actions def openEditWindow(self, viewName='edit.html'): if self.editable: diff --git a/browser/concept.py b/browser/concept.py index 339a659..d1f896e 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -46,7 +46,7 @@ from cybertools.typology.interfaces import IType, ITypeManager from loops.interfaces import IConcept from loops.interfaces import ITypeConcept from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList -from loops.browser.common import EditForm, BaseView, LoopsTerms +from loops.browser.common import EditForm, BaseView, LoopsTerms, conceptMacrosTemplate from loops import util from loops.util import _ from loops.versioning.util import getVersion @@ -75,12 +75,16 @@ class ConceptEditForm(EditForm): class ConceptView(BaseView): - template = NamedTemplate('loops.concept_macros') + template = ViewPageTemplateFile('concept_macros.pt') @Lazy def macro(self): return self.template.macros['conceptdata'] + @Lazy + def conceptMacros(self): + return conceptMacrosTemplate.macros + def __init__(self, context, request): super(ConceptView, self).__init__(context, request) cont = self.controller diff --git a/browser/form.py b/browser/form.py index 37b6496..b7eb5b7 100644 --- a/browser/form.py +++ b/browser/form.py @@ -394,13 +394,15 @@ class CreateObject(EditObject): name = name.rsplit('\\', 1)[-1] else: name = None + # TODO: validate fields name = INameChooser(container).chooseName(name, obj) container[name] = obj tc = form.get('form.type') or '.loops/concepts/note' obj.resourceType = self.loopsRoot.loopsTraverse(tc) notify(ObjectCreatedEvent(obj)) self.object = obj - self.updateFields() - self.request.response.redirect(self.view.virtualTargetUrl) + self.updateFields() # TODO: suppress validation + #self.request.response.redirect(self.view.virtualTargetUrl) + self.request.response.redirect(self.view.request.URL) return False diff --git a/browser/node.py b/browser/node.py index 674ab7f..d89e5ad 100644 --- a/browser/node.py +++ b/browser/node.py @@ -51,6 +51,7 @@ from loops.interfaces import IViewConfiguratorSchema from loops.resource import MediaAsset from loops import util from loops.util import _ +from loops.browser.action import Action, TargetAction from loops.browser.common import BaseView from loops.browser.concept import ConceptView from loops.versioning.util import getVersion @@ -162,11 +163,6 @@ class NodeView(BaseView): basicView._viewName = self.context.viewName return basicView.view - #@Lazy - #def target(self): - # # obsolete and confusing - TODO: remove... - # return self.targetObjectView - @Lazy def targetUrl(self): t = self.targetObjectView @@ -334,11 +330,31 @@ class NodeView(BaseView): # target viewing and editing support + def getUrlForTarget(self, target): + """ Return URL of given target view given as .targetXXX URL. + """ + return '%s/.target%s' % (self.url, target.uniqueId) + def getActions(self, category='object'): - #target = self.virtualTarget - #if target is not None: - # return target.getActions(category) - return [] # TODO: what about editing the node itself? + actions = [] + self.registerDojo() + if category in self.actions: + actions.extend(self.actions[category](self)) + target = self.virtualTarget + if target is not None: + actions.extend(target.getActions(category, page=self)) + return actions + + def getPortletActions(self): + actions = [] + actions.append(Action(self, + targetWindow='loops_cme', + title='Edit Concept Map', + description='Open concept map editor in new window', + url=self.conceptMapEditorUrl)) + return actions + + actions = dict(portlet=getPortletActions) @Lazy def hasEditableTarget(self): diff --git a/browser/node_macros.pt b/browser/node_macros.pt index 412bee2..ade3466 100644 --- a/browser/node_macros.pt +++ b/browser/node_macros.pt @@ -208,17 +208,11 @@ + + + -
- - Edit Concept Map - -
\n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -194,6 +194,9 @@ msgstr "major" msgid "minor" msgstr "minor" +msgid "see" +msgstr "siehe" + msgid "Change Password" msgstr "Passwort ändern"