mirror of
https://github.com/edgewall/trac.git
synced 2026-02-06 03:46:55 +01:00
[skip ci] git-svn-id: http://trac.edgewall.org/intertrac/log:/trunk@17657 af82e41b-90c4-0310-8c96-b1721e28e2e2
129 lines
4.7 KiB
Python
129 lines
4.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2007-2023 Edgewall Software
|
|
# Copyright (C) 2007 Eli Carter <retracile@gmail.com>
|
|
# All rights reserved.
|
|
#
|
|
# This software is licensed as described in the file COPYING, which
|
|
# you should have received as part of this distribution. The terms
|
|
# are also available at https://trac.edgewall.org/wiki/TracLicense.
|
|
#
|
|
# This software consists of voluntary contributions made by many
|
|
# individuals. For the exact contribution history, see the revision
|
|
# history and logs, available at https://trac.edgewall.org/.
|
|
|
|
from collections import OrderedDict
|
|
|
|
from trac.core import Component, implements
|
|
from trac.perm import IPermissionRequestor
|
|
from trac.ticket.api import ITicketActionController
|
|
from trac.ticket.default_workflow import ConfigurableTicketWorkflow
|
|
from trac.util import to_list
|
|
from trac.util.html import tag
|
|
|
|
revision = "$Rev$"
|
|
url = "$URL$"
|
|
|
|
|
|
class CodeReviewActionController(Component):
|
|
"""Support for simple code reviews.
|
|
|
|
The action that supports the `code_review` operation will present
|
|
an extra choice for the review decision. Depending on that decision,
|
|
a specific state will be selected.
|
|
|
|
Example (from the enterprise-review-workflow.ini):
|
|
{{{#!ini
|
|
request_review = in_work -> in_review
|
|
review = in_review -> *
|
|
review.operations = code_review
|
|
review.code_review =
|
|
approve -> in_QA,
|
|
approve as noted -> post_review,
|
|
request changes -> in_work
|
|
}}}
|
|
|
|
Don't forget to add the `CodeReviewActionController` to the workflow
|
|
option in the `[ticket]` section in TracIni. When added to the default
|
|
value of `workflow`, the line will look like this:
|
|
{{{#!ini
|
|
workflow = ConfigurableTicketWorkflow,CodeReviewActionController
|
|
}}}
|
|
"""
|
|
|
|
implements(IPermissionRequestor, ITicketActionController)
|
|
|
|
# IPermissionRequestor methods
|
|
|
|
def get_permission_actions(self):
|
|
return ['TICKET_REVIEW']
|
|
|
|
# ITicketActionController methods
|
|
|
|
def get_ticket_actions(self, req, ticket):
|
|
# The review action is available in those status where it has been
|
|
# configured, for those users who have the TICKET_REVIEW permission, as
|
|
# long as they are not the owner of the ticket (you can't review your
|
|
# own work).
|
|
actions_we_handle = []
|
|
if req.authname != ticket['owner'] and \
|
|
'TICKET_REVIEW' in req.perm(ticket.resource):
|
|
controller = ConfigurableTicketWorkflow(self.env)
|
|
actions_we_handle = controller.get_actions_by_operation_for_req(
|
|
req, ticket, 'code_review')
|
|
self.log.debug('code review handles actions: %r', actions_we_handle)
|
|
return actions_we_handle
|
|
|
|
def get_all_status(self):
|
|
all_status = set()
|
|
controller = ConfigurableTicketWorkflow(self.env)
|
|
for weight, action \
|
|
in controller.get_actions_by_operation('code_review'):
|
|
review_options = self._get_review_options(action)
|
|
all_status.update(iter(review_options.values()))
|
|
return all_status
|
|
|
|
def render_ticket_action_control(self, req, ticket, action):
|
|
id, selected = self._get_selected(req, action)
|
|
|
|
review_options = self._get_review_options(action)
|
|
actions = ConfigurableTicketWorkflow(self.env).actions
|
|
|
|
label = actions[action]['label']
|
|
control = tag(["as: ",
|
|
tag.select([
|
|
tag.option(option,
|
|
selected=(option == selected or None))
|
|
for option in review_options],
|
|
name=id, id=id)])
|
|
if selected:
|
|
new_status = self._get_new_status(req, action, review_options)
|
|
hint = "Next status will be '%s'" % new_status
|
|
else:
|
|
hint = "Next status will be one of " + \
|
|
', '.join("'%s'" % st for st in review_options.values())
|
|
return label, control, hint
|
|
|
|
def get_ticket_changes(self, req, ticket, action):
|
|
new_status = self._get_new_status(req, action)
|
|
return {'status': new_status or 'new'}
|
|
|
|
def apply_action_side_effects(self, req, ticket, action):
|
|
pass
|
|
|
|
# Internal methods
|
|
|
|
def _get_selected(self, req, action):
|
|
id = 'action_%s_code_review' % action
|
|
return id, req.args.get(id)
|
|
|
|
def _get_review_options(self, action):
|
|
values = self.config.getlist('ticket-workflow', action + '.code_review')
|
|
return OrderedDict(to_list(v, sep='->') for v in values)
|
|
|
|
def _get_new_status(self, req, action, review_options=None):
|
|
selected = self._get_selected(req, action)[1]
|
|
if not review_options:
|
|
review_options = self._get_review_options(action)
|
|
return review_options[selected]
|