provide state icon with link to state transition form for comments

This commit is contained in:
Helmut Merz 2014-04-09 13:07:39 +02:00
parent 61cfff0f91
commit a47b6a02a0
4 changed files with 59 additions and 12 deletions

View file

@ -22,6 +22,7 @@ Base classes for comments/discussions.
from zope.component import adapts from zope.component import adapts
from zope.interface import implementer, implements from zope.interface import implementer, implements
from zope.traversing.api import getParent
from cybertools.stateful.definition import StatesDefinition from cybertools.stateful.definition import StatesDefinition
from cybertools.stateful.definition import State, Transition from cybertools.stateful.definition import State, Transition
@ -38,7 +39,7 @@ def commentStates():
return StatesDefinition('commentStates', return StatesDefinition('commentStates',
State('new', 'new', ('accept', 'reject'), color='red'), State('new', 'new', ('accept', 'reject'), color='red'),
State('public', 'public', ('retract', 'reject'), color='green'), State('public', 'public', ('retract', 'reject'), color='green'),
State('rejected', 'rejected', ('accept'), color='grey'), State('rejected', 'rejected', ('accept',), color='grey'),
Transition('accept', 'accept', 'public'), Transition('accept', 'accept', 'public'),
Transition('reject', 'reject', 'rejected'), Transition('reject', 'reject', 'rejected'),
Transition('retract', 'retract', 'new'), Transition('retract', 'retract', 'new'),
@ -61,3 +62,11 @@ class Comment(Stateful, Track):
super(Comment, self).__init__(taskId, runId, userName, data) super(Comment, self).__init__(taskId, runId, userName, data)
self.state = self.getState() # make initial state persistent self.state = self.getState() # make initial state persistent
@property
def title(self):
return self.data['subject']
def doTransition(self, action):
super(Comment, self).doTransition(action)
getParent(self).indexTrack(None, self, 'state')

View file

@ -88,9 +88,17 @@ class CommentsView(NodeView):
def getActionsFor(self, comment): def getActionsFor(self, comment):
if not checkPermission('loops.ViewRestricted', self.context): if not checkPermission('loops.ViewRestricted', self.context):
return [] return []
trackUid = util.getUidForObject(comment.track)
url = '%s/.%s/change_state.html' % (
self.page.virtualTargetUrl, trackUid)
onClick = ("objectDialog('change_state', "
"'%s?dialog=change_state"
"&target_uid=%s'); return false;" % (url, trackUid))
stateAct = StateAction(self, stateAct = StateAction(self,
definition='organize.commentStates', definition='organize.commentStates',
stateful=comment.track) stateful=comment.track,
url=url,
onClick=onClick)
return [stateAct] return [stateAct]

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de # Copyright (c) 2014 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
@ -36,6 +36,7 @@ from loops.browser.form import ObjectForm, EditObject
from loops.expert.query import And, Or, State, Type, getObjects from loops.expert.query import And, Or, State, Type, getObjects
from loops.expert.browser.search import search_template from loops.expert.browser.search import search_template
from loops.security.common import checkPermission from loops.security.common import checkPermission
from loops import util
from loops.util import _ from loops.util import _
@ -97,8 +98,10 @@ class ChangeStateBase(object):
@Lazy @Lazy
def stateful(self): def stateful(self):
return component.getAdapter(self.view.virtualTargetObject, IStateful, target = self.view.virtualTargetObject
name=self.definition) if IStateful.providedBy(target):
return target
return component.getAdapter(target, IStateful, name=self.definition)
@Lazy @Lazy
def definition(self): def definition(self):
@ -110,6 +113,7 @@ class ChangeStateBase(object):
@Lazy @Lazy
def transition(self): def transition(self):
if self.action:
return self.stateful.getStatesDefinition().transitions[self.action] return self.stateful.getStatesDefinition().transitions[self.action]
@Lazy @Lazy
@ -143,8 +147,17 @@ class ChangeStateForm(ChangeStateBase, ObjectForm):
class ChangeState(ChangeStateBase, EditObject): class ChangeState(ChangeStateBase, EditObject):
@Lazy
def stateful(self):
target = self.target
if IStateful.providedBy(target):
return target
return component.getAdapter(target, IStateful, name=self.definition)
def update(self): def update(self):
formData = self.request.form formData = self.request.form
if 'target_uid' in formData:
self.target = util.getObjectForUid(formData['target_uid'])
# store data in target object (unless field.nostore) # store data in target object (unless field.nostore)
self.object = self.target self.object = self.target
formState = self.instance.applyTemplate(data=formData) formState = self.instance.applyTemplate(data=formData)
@ -159,7 +172,7 @@ class ChangeState(ChangeStateBase, EditObject):
rawValue = fi.getRawValue(formData, name, u'') rawValue = fi.getRawValue(formData, name, u'')
trackData[name] = fi.unmarshall(rawValue) trackData[name] = fi.unmarshall(rawValue)
self.stateful.doTransition(self.action) self.stateful.doTransition(self.action)
notify(ObjectModifiedEvent(self.view.virtualTargetObject, trackData)) notify(ObjectModifiedEvent(self.target, trackData))
return True return True

View file

@ -114,16 +114,33 @@
tal:define="stateObject view/stateful/getStateObject" tal:define="stateObject view/stateful/getStateObject"
tal:content="stateObject/title" /> - tal:content="stateObject/title" /> -
<span i18n:translate="">Transition</span>: <span i18n:translate="">Transition</span>:
<tal:transition condition="view/transition">
<span i18n:translate="" <span i18n:translate=""
tal:content="view/transition/title" /> tal:content="view/transition/title" />
<input type="hidden" name="action"
tal:attributes="value request/form/action|nothing">
</tal:transition>
<tal:transition condition="not:view/transition">
<tal:trans repeat="trans view/stateful/getAvailableTransitions">
<label i18n:translate=""
tal:attributes="for string:transition.${trans/name}"
tal:content="trans/title" />
<input type="radio" name="action"
tal:attributes="value trans/name;
id string:transition.${trans/name}" />
</tal:trans>
</tal:transition>
</div> </div>
<input type="hidden" name="form.action" value="change_state"> <input type="hidden" name="form.action" value="change_state">
<input type="hidden" name="stdef" <input type="hidden" name="stdef"
tal:attributes="value request/form/stdef|nothing"> tal:attributes="value request/form/stdef|nothing">
<input type="hidden" name="action" <input type="hidden" name="target_uid"
tal:attributes="value request/form/action|nothing"> tal:define="uid request/target_uid|nothing"
tal:condition="uid"
tal:attributes="value uid" />
</div> </div>
<div dojoType="dijit.layout.ContentPane" region="center"> <div dojoType="dijit.layout.ContentPane" region="center"
tal:condition="view/transition">
<table cellpadding="3" class="form"> <table cellpadding="3" class="form">
<tbody><tr><td colspan="5" style="padding-right: 15px"> <tbody><tr><td colspan="5" style="padding-right: 15px">
<div id="form.fields"> <div id="form.fields">