| from genshi.builder import tag |
| |
| from trac.core import implements,Component |
| from trac.ticket.api import ITicketActionController |
| from trac.ticket.default_workflow import ConfigurableTicketWorkflow |
| from trac.perm import IPermissionRequestor |
| from trac.config import Option, ListOption |
| |
| revision = "$Rev: 11490 $" |
| url = "$URL: http://svn.edgewall.org/repos/trac/tags/trac-1.0.1/sample-plugins/workflow/CodeReview.py $" |
| |
| 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): |
| {{{ |
| review = in_review -> * |
| review.name = review as |
| 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. |
| If there is no other workflow option, the line will look like this: |
| {{{ |
| workflow = ConfigurableTicketWorkflow,CodeReviewActionController |
| }}} |
| """ |
| |
| implements(ITicketActionController, IPermissionRequestor) |
| |
| # 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) |
| ouractions = controller.get_actions_by_operation('code_review') |
| for weight, action in ouractions: |
| status = [status for option, status in |
| self._get_review_options(action)] |
| all_status.update(status) |
| return all_status |
| |
| def render_ticket_action_control(self, req, ticket, action): |
| id, grade = self._get_grade(req, action) |
| |
| review_options = self._get_review_options(action) |
| actions = ConfigurableTicketWorkflow(self.env).actions |
| |
| selected_value = grade or review_options[0][0] |
| |
| label = actions[action]['name'] |
| control = tag(["as: ", |
| tag.select([tag.option(option, selected= |
| (option == selected_value or |
| None)) |
| for option, status in review_options], |
| name=id, id=id)]) |
| if grade: |
| new_status = self._get_new_status(req, ticket, action, |
| review_options) |
| hint = "Next status will be '%s'" % new_status |
| else: |
| hint = "Next status will be one of " + \ |
| ', '.join(["'%s'" % status |
| for option, status in review_options]) |
| return (label, control, hint) |
| |
| def get_ticket_changes(self, req, ticket, action): |
| new_status = self._get_new_status(req, ticket, action) |
| return {'status': new_status or 'new'} |
| |
| def apply_action_side_effects(self, req, ticket, action): |
| pass |
| |
| # Internal methods |
| |
| def _get_grade(self, req, action): |
| id = action + '_code_review_result' |
| return id, req.args.get(id) |
| |
| def _get_review_options(self, action): |
| return [[x.strip() for x in raw_option.split('->')] |
| for raw_option in self.config.getlist('ticket-workflow', |
| action + '.code_review')] |
| |
| def _get_new_status(self, req, ticket, action, review_options=None): |
| id, grade = self._get_grade(req, action) |
| if not review_options: |
| review_options = self._get_review_options(action) |
| for option, status in review_options: |
| if grade == option: |
| return status |