def change_workflow_config(self, lines): for (option, value) in lines: self.env.config.set('ticket-workflow', option, value) self.env.config.save() self.clear_ticket_system_field_cache() ticket_workflow = ConfigurableTicketWorkflow(self.env) ticket_workflow.actions = get_workflow_config(self.env.config)
def get_ticket_changes(self, req, ticket, action): this_action = ConfigurableTicketWorkflow(self.env).actions[action] # Enforce permissions if not 'TICKET_MODIFY' in req.perm(ticket.resource): # The user does not have any of the listed permissions, so we won't # do anything. return {} updated = {} # Status changes status = this_action['newstate'] if status != '*': updated['status'] = status for operation in this_action['operations']: if operation == 'del_evaluation': updated['evaluation'] = '' elif operation == 'set_evaluation': newevaluation = req.args.get( 'action_%s_evaluate_evaluation' % action, this_action.get('set_evaluation', '').strip()) updated['evaluation'] = newevaluation return updated
def _get_action_controls(self, req, tickets): action_controls = [] ts = TicketSystem(self.env) tickets_by_action = {} for t in tickets: ticket = Ticket(self.env, t['id']) available_actions = ts.get_available_actions(req, ticket) for action in available_actions: tickets_by_action.setdefault(action, []).append(ticket) # Sort the allowed actions by the 'default' key. allowed_actions = set(tickets_by_action.keys()) workflow = ConfigurableTicketWorkflow(self.env) all_actions = sorted( ((action['default'], name) for name, action in workflow.get_all_actions().iteritems()), reverse=True) sorted_actions = [ action[1] for action in all_actions if action[1] in allowed_actions ] for action in sorted_actions: first_label = None hints = [] widgets = [] ticket = tickets_by_action[action][0] for controller in self._get_action_controllers( req, ticket, action): label, widget, hint = controller.render_ticket_action_control( req, ticket, action) if not first_label: first_label = label widgets.append(widget) hints.append(hint) action_controls.append((action, first_label, tag(widgets), hints)) return action_controls
def get_ticket_changes(self, req, ticket, action): this_action = ConfigurableTicketWorkflow(self.env).actions[action] # Enforce permissions if not 'TICKET_MODIFY' in req.perm(ticket.resource): # The user does not have any of the listed permissions, so we won't # do anything. return {} updated = {} # Status changes status = this_action['newstate'] if status != '*': updated['status'] = status for operation in this_action['operations']: if operation == 'del_evaluation': updated['evaluation'] = '' elif operation == 'set_evaluation': newevaluation = req.args.get('action_%s_evaluate_evaluation' % action, this_action.get('set_evaluation', '').strip()) updated['evaluation'] = newevaluation return updated
def get_ticket_actions(self, req, ticket): actions_we_handle = [] if req.authname != "anonymous" and "TICKET_MODIFY" in req.perm(ticket.resource): controller = ConfigurableTicketWorkflow(self.env) actions_we_handle = controller.get_actions_by_operation_for_req(req, ticket, "set_milestone") self.log.debug("set_milestone handles actions: %r", actions_we_handle) return actions_we_handle
def change_workflow_config(self, lines): for (option, value) in lines: self.env.config.set('ticket-workflow', option, value) self.env.config.save() self.clear_ticket_system_field_cache() ticket_workflow = ConfigurableTicketWorkflow(self.env) ticket_workflow.actions = get_workflow_config(self.env.config)
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(review_options.itervalues()) return all_status
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 get_ticket_actions(self, req, ticket): actions_we_handle = [] if req.is_authenticated and \ 'TICKET_MODIFY' in req.perm(ticket.resource): controller = ConfigurableTicketWorkflow(self.env) actions_we_handle = controller.get_actions_by_operation_for_req( req, ticket, 'set_milestone') self.log.debug('set_milestone 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 get_ticket_actions(self, req, ticket): actions_we_handle = [] if 'TICKET_MODIFY' in req.perm(ticket.resource): controller = ConfigurableTicketWorkflow(self.env) actions_we_handle += controller.get_actions_by_operation_for_req( req, ticket, 'set_evaluation') actions_we_handle += controller.get_actions_by_operation_for_req( req, ticket, 'del_evaluation') self.log.debug('evaluation handles actions: %r' % actions_we_handle) return actions_we_handle
def get_ticket_actions(self, req, ticket): actions_we_handle = [] if 'TICKET_MODIFY' in req.perm(ticket.resource): controller = ConfigurableTicketWorkflow(self.env) actions_we_handle += controller.get_actions_by_operation_for_req( req, ticket, 'set_evaluation') actions_we_handle += controller.get_actions_by_operation_for_req( req, ticket, 'del_evaluation') self.log.debug('evaluation handles actions: %r' % actions_we_handle) return actions_we_handle
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 test_ignores_other_operations(self): """Ignores operations not defined by ConfigurableTicketWorkflow. """ self.env.config.set('ticket-workflow', 'review', 'assigned -> review') self.env.config.set('ticket-workflow', 'review.operations', 'CodeReview') ctw = ConfigurableTicketWorkflow(self.env) ticket = Ticket(self.env) ticket.populate({'summary': '#13013', 'status': 'assigned'}) ticket.insert() req = MockRequest(self.env) self.assertNotIn((0, 'review'), ctw.get_ticket_actions(req, ticket))
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 apply_action_side_effects(self, req, ticket, action): """Add a cross-reference comment to the other ticket""" # TODO: This needs a lot more error checking. id = 'action_%s_xref' % action ticketnum = req.args.get(id).strip('#') actions = ConfigurableTicketWorkflow(self.env).actions author = req.authname # Add a comment to the "remote" ticket to indicate this ticket is # related to it. format_string = actions[action].get('xref', 'Ticket %s is related to this ticket') comment = format_string % ('#%s' % ticket.id) # FIXME: This assumes the referenced ticket exists. xticket = model.Ticket(self.env, ticketnum) # FIXME: We _assume_ we have sufficient permissions to comment on the # other ticket. xticket.save_changes(author, comment) # Add a comment to this ticket to indicate that the "remote" ticket is # related to it. (But only if <action>.xref_local was set in the # config.) format_string = actions[action].get('xref_local', 'Ticket %s was marked as related to this ticket') if format_string: comment = format_string % ('#%s' % ticketnum) time.sleep(1) # FIXME: Hack around IntegrityError # HACK: Grab a new ticket object to avoid getting # "OperationalError: no such column: new" xticket = model.Ticket(self.env, ticket.id) xticket.save_changes(author, comment)
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 render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] hint = 'The owner will change to %s' % ticket['reporter'] control = tag('') return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['label'] res_ms = self.__get_resolution_milestone_dict(ticket, action) resolutions = '' milestone = None for i, resolution in enumerate(res_ms): if i > 0: resolutions = "%s, '%s'" % (resolutions, resolution) else: resolutions = "'%s'" % resolution milestone = res_ms[resolution] hint = None if res_ms: try: Milestone(self.env, milestone) except ResourceNotFound: pass else: hint = _( "For resolution %(resolutions)s the milestone will " "be set to '%(milestone)s'.", resolutions=resolutions, milestone=milestone) return label, None, hint
def _get_ticket_transitions(self): groups_config = self.env.config['itteco-whiteboard-groups'] if self._old_groups!=groups_config or self._transitions is None: actions = ConfigurableTicketWorkflow(self.env).actions transitions = [ { 'newstatus': act_info['newstate'], 'action': act_id, 'oldstatuses':act_info['oldstates'] } \ for act_id, act_info in actions.iteritems() if act_id!='_reset' ] self.env.log.debug('transitions="%s"' % transitions) self._transitions = transitions return self._transitions
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['label'] hint = _("The '%(field)s' field will be set to '%(username)s'.", field=self._field_name(action, ticket), username=req.authname) control = html('') return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] hint = self.config.get('ticket-workflow', action + '.run_external').strip() if hint is None: hint = "Will run external script." return (label, tag(''), hint)
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" id = 'action_%s_xref' % action ticketnum = req.args.get(id, '') actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] hint = actions[action].get('xref_hint', 'The specified ticket will be cross-referenced with this ticket') control = tag.input(type='text', id=id, name=id, value=ticketnum) return (label, control, hint)
class TaskBoardChangeHandler(Component): implements(IRequestHandler) def __init__(self): self.controller = ConfigurableTicketWorkflow(self.env) # IRequestHandler methods def match_request(self, req): return req.path_info == '/taskboard' def process_request(self, req): self.env.log.debug("taskboard API received: %s" % req.args) if not req.args.get('id') or not req.args.get('status'): self._write_response(req, 400, {}) return ticket = Ticket(self.env, int(req.args['id'])) ticket_available_actions = [] for weight, action in self.controller.get_ticket_actions(req, ticket): changes = self.controller.get_ticket_changes(req, ticket, action) if not changes.get('status'): continue if changes['status'] == req.args['status']: ticket_available_actions.append([ weight, action ]) ticket_available_actions.sort() self.env.log.debug("taskboard API actions: %s" % ticket_available_actions) if len(ticket_available_actions) > 0: actions = ticket_available_actions.pop() self._write_response(req, 200, { 'action': actions[1] }) else: self._write_response(req, 400, {}) def _write_response(self, req, status=200, data={}): body = json.dumps(data) req.send_response(int(status)) req.send_header('Content-Type', 'application/json; charset=UTF-8') req.send_header('Content-Length', str(len(body))) req.send_header('Cache-Control', 'no-cache') req.end_headers() req.write(body)
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] new_owner = self._new_owner(ticket) if new_owner: hint = 'The owner will change to %s' % new_owner else: hint = 'The owner will be deleted.' control = tag('') return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['label'] fields = ["'%s'" % x for x in self._field_names(action, ticket)] hint = ngettext("The %(fields)s field will be cleared.", "The %(fields)s fields will be cleared.", len(fields), fields=', '.join(fields)) control = html('') return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] new_status = self._new_status(ticket, action) if new_status != ticket['status']: hint = 'The status will change to %s.' % new_status else: hint = '' control = tag('') return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] # check if the assigned milestone has been completed milestone = Milestone(self.env,ticket['milestone']) if milestone.is_completed: hint = 'The milestone will be reset' else: hint = '' control = tag('') return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] res_ms = self.__get_resolution_milestone_dict(ticket, action) resolutions = '' milestone = None for i, resolution in enumerate(res_ms): if i > 0: resolutions = "%s, '%s'" % (resolutions, resolution) else: resolutions = "'%s'" % resolution milestone = res_ms[resolution] hint = _("For resolution %(resolutions)s the milestone will be " "set to '%(milestone)s'.", resolutions=resolutions, milestone=milestone) return (label, None, hint)
def render_ticket_action_control(self, req, ticket, action): this_action = ConfigurableTicketWorkflow(self.env).actions[action] status = this_action['newstate'] operations = this_action['operations'] control = [] # default to nothing hints = [] if 'set_evaluation' in operations: evaluations = self._get_evaluation_options() if not evaluations: raise TracError( _('Your workflow attempts to set an evaluation ' 'but none is defined (configuration issue, ' 'please contact your Trac admin).')) id = 'action_%s_evaluate_evaluation' % action if len(evaluations) == 1: evaluation = tag.input(type='hidden', id=id, name=id, value=evaluations[0]) control.append( tag_('as %(evaluation)s', evaluation=tag(evaluations[0], evaluation))) hints.append( _('The evaluation will be set to %(name)s', name=evaluations[0])) else: selected_option = 1 control.append( tag_( 'as %(evaluation)s', evaluation=tag.select([ tag.option(x, value=x, selected=(x == selected_option or None)) for x in evaluations ], id=id, name=id))) hints.append(_('The evaluation will be set')) #if 'del_evaluation' in operations: # hints.append(_('The evaluation will be deleted')) return (this_action['name'], tag(*control), '. '.join(hints) + '.' if hints else '')
def render_ticket_action_control(self, req, ticket, action): actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['label'] hint = None old_milestone = ticket._old.get('milestone') if old_milestone is None: resolutions, milestone = \ self._get_resolutions_and_milestone(action) if resolutions: try: Milestone(self.env, milestone) except ResourceNotFound: pass else: res_hint = ', '.join("'%s'" % r for r in resolutions) hint = _("For resolution %(resolutions)s the milestone " "will be set to '%(milestone)s'.", resolutions=res_hint, milestone=milestone) return label, None, hint
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.itervalues()) return label, control, hint
def get_ticket_actions(self, req, ticket): actions = \ ConfigurableTicketWorkflow.get_ticket_actions(self, req, ticket) actions = self.filter_actions(actions, ticket) return actions
def get_ticket_actions(self, req, ticket): """Finds the actions that use this operation""" controller = ConfigurableTicketWorkflow(self.env) return controller.get_actions_by_operation_for_req(req, ticket, 'run_external')
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['name'] return (label, tag(''), '')
def get_ticket_actions(self, req, ticket): """Finds the actions that use this operation""" controller = ConfigurableTicketWorkflow(self.env) return controller.get_actions_by_operation_for_req(req, ticket, 'run_external')
def get_ticket_actions(self, req, ticket): controller = ConfigurableTicketWorkflow(self.env) return controller.get_actions_by_operation_for_req(req, ticket, 'vote')
def get_configurable_workflow(self): controllers = TicketSystem(self.env).action_controllers for controller in controllers: if isinstance(controller, ConfigurableTicketWorkflow): return controller return ConfigurableTicketWorkflow(self.env)
def get_ticket_actions(self, req, ticket): actions = ConfigurableTicketWorkflow.get_ticket_actions(self, req, ticket) actions = self.filter_actions(actions, ticket) return actions
def get_ticket_actions(self, req, ticket): controller = ConfigurableTicketWorkflow(self.env) return controller.get_actions_by_operation_for_req(req, ticket, 'vote')
def __init__(self): self.controller = ConfigurableTicketWorkflow(self.env)