Edgewall Software

Ticket #4686 (closed enhancement: fixed)

Opened 22 months ago

Last modified 2 months ago

Ticket duplication using Trac

Reported by: olivermn@… Owned by: cboos
Priority: normal Milestone: 0.11
Component: ticket system Version:
Severity: normal Keywords: copy clone
Cc:

Description (last modified by cboos) (diff)

It should be possible to create a new ticket by duplicating an existing ticket.

Use Cases

(from #th1214)

We just migrated to Trac from Bugzilla. The only feature we miss is the ability to clone a ticket into the new ticket fields. It would be great to have the Clone a Trac Ticket functionality.

(original request)

I'm hoping this has been done before and I'm just unable to find it. I have a collection of HW which assigns tasks to multiple teams when it arrives. To help manage this data I want to use Trac tasks. I have a GUI front end which solicits for all the data required in creating a task. It also solicits which teams are impacted. I want to create as many issues as there are teams impacted with the components of each driving the owner.

I then want to be able to use the front end to manage status on each of the opened tasks. So tickets 45, 46, 47 might all have the same data but have different components where Teams A, B, and C all have very different assignments.

I don't wish to reinvent the wheel. Is something similar to this already done?

tracking the status of an issue in different release lines

When there's a regression for a bug, instead of reopening the ticket (which will loose the information that this bug has been effectively fixed for the milestone indicated), one could duplicate it and schedule it for a given milestone on the other release line, see #4298.

creating ticket templates

One could have a wiki page with links to a few "typical" tickets that could be used as a templates for creating new tickets. Such tickets could have among other things prefilled descriptions, see #4044.

Attachments

clone_as_action.png (20.8 KB) - added by cboos 19 months ago.
Yet another possibility, the "clone" as an action distinct from the ones modifying the ticket itself

Change History

  Changed 22 months ago by anonymous

  • status changed from new to closed
  • resolution set to wontfix

As the author I wish to cancel.

  Changed 22 months ago by cboos

(this proposal sounded a bit like the "clone ticket" functionality ... not sure there's already a ticket opened for that though)

  Changed 21 months ago by anonymous

  • status changed from closed to reopened
  • resolution wontfix deleted

This is essentially cloning an existing ticket. Not an easy way to do this from my perspective. Have been trying to either use the macros to facilitate or to use eggs. Neither has been fruitful to date. What is the timeline for having clone feature. I found a clone defect that was a year old.

  Changed 21 months ago by cboos

  • keywords copy clone added
  • summary changed from Front-end display and duplication using Trac to Ticket duplication using Trac
  • milestone set to 1.0

What is the timeline for having clone feature. I found a clone defect that was a year old.

I was looking for a duplicate of this request but didn't find it... care to give the ticket number?

I agree that a Clone Ticket functionality can be useful in some scenarios, like one way to deal with the single issue, multiple releases problem (see #4298), or creating ticket templates (see #4044).

  Changed 21 months ago by olivermn@…

I have written by own version and I'll post those changes here shortly. Up to you if you'd like to use this to close the other clone issue.

follow-up: ↓ 7   Changed 21 months ago by ThurnerRupert <rupert.thurner@…>

closed the other one as inferior proposal.

in reply to: ↑ 6   Changed 21 months ago by schandler@…

Replying to ThurnerRupert <rupert.thurner@gmail.com>:

closed the other one as inferior proposal.

FYI: There is still another clone request #T1214 out there that is different enough, imho, from this ticket.

follow-up: ↓ 9   Changed 21 months ago by cboos

  • description modified (diff)

#Th1214 you meant ;-)

Well, I agree that the original description was not explicitly targeted at ticket duplication, it's only because of comment:2 and comment:3 that this ticket has been focused on the ticket cloning topic. I'll cleanup the description to reflect that, as otherwise I think that #Th1214 should be implemented in the base ticket system, for the reasons mentioned in comment:4.

in reply to: ↑ 8   Changed 21 months ago by schandler@…

Replying to cboos:

#Th1214 you meant ;-) Well, I agree that the original description was not explicitly targeted at ticket duplication, it's only because of comment:2 and comment:3 that this ticket has been focused on the ticket cloning topic. I'll cleanup the description to reflect that, as otherwise I think that #Th1214 should be implemented in the base ticket system, for the reasons mentioned in comment:4.

yep. I goofed up. 1214 is on Trac-hacks. Thanks for the correction! I'll be more careful about that.

  Changed 21 months ago by anonymous

I forgot about this work.

I made two changes to allow a version of cloning The first was in the style sheet.

/usr/share/trac/template/ticket.cs
 <div class="buttons">
  <input type="hidden" name="ts" value="<?cs var:ticket.ts ?>" />
  <input type="hidden" name="replyto" value="<?cs var:ticket.replyto ?>" />
  <input type="hidden" name="cnum" value="<?cs var:ticket.cnum ?>" />
  <input type="submit" name="preview" value="Preview" accesskey="r" />&nbsp;
  <input type="submit" value="Submit changes" />
  <p>
  <input type="submit" name="clone" value="Clone" />&nbsp;
 </div>



Only 2 new lines in the above:
335,336d333
<   <p>
<   <input type="submit" name="clone" value="Clone" />&nbsp;

The second change was to
/usr/lib/python2-3/site-packages/trac/ticket/web_ui.py

where I made a copy new ticket in a clone request

    def clone_request(self, req, db):
        req.perm.assert_permission('TICKET_CREATE')

        db = self.env.get_db_cnx()

        if req.method == 'POST' and 'owner' in req.args and \
               not req.perm.has_permission('TICKET_MODIFY'):
            del req.args['owner']

        if not req.args.get('summary'):
            raise TracError('Tickets must contain a summary.')

        ticket = Ticket(self.env, db=db)
        ticket.populate(req.args)
        ticket.values['reporter'] = get_reporter_id(req, 'reporter')
        ticket['status'] = 'new'
        self._validate_ticket(req, ticket)

        ticket.insert(db=db)
        db.commit()

        # Notify
        try:
            tn = TicketNotifyEmail(self.env)
            tn.notify(ticket, newticket=True)
        except Exception, e:
            self.log.exception("Failure sending notification on creation of "
                               "ticket #%s: %s" % (ticket.id, e))

        # Redirect the user to the newly created ticket
        if req.args.get('attachment'):
            req.redirect(req.href.attachment('ticket', ticket.id, action='new'))
        else:
            req.redirect(req.href.ticket(ticket.id))

        ticket = Ticket(self.env, db=db)
        ticket.populate(req.args)
        ticket.values['reporter'] = get_reporter_id(req, 'reporter')

        if ticket.values.has_key('description'):
            description = wiki_to_html(ticket['description'], self.env, req, db)
            req.hdf['newticket.description_preview'] = description

        req.hdf['title'] = 'New Ticket'
        req.hdf['newticket'] = ticket.values

        field_names = [field['name'] for field in ticket.fields
                       if not field.get('custom')]
        if 'owner' in field_names:
            curr_idx = field_names.index('owner')
            if 'cc' in field_names:
                insert_idx = field_names.index('cc')
            else:
                insert_idx = len(field_names)
            if curr_idx < insert_idx:
                ticket.fields.insert(insert_idx, ticket.fields[curr_idx])
                del ticket.fields[curr_idx]

        for field in ticket.fields:
            name = field['name']
            del field['name']
            if name in ('summary', 'reporter', 'description', 'type', 'status',
                        'resolution'):
                field['skip'] = True
            elif name == 'owner':
                field['label'] = 'Assign to'
                if not req.perm.has_permission('TICKET_MODIFY'):
                    field['skip'] = True
            elif name == 'milestone':
                # Don't make completed milestones available for selection
                options = field['options'][:]
                for option in field['options']:
                    milestone = Milestone(self.env, option, db=db)
                    if milestone.is_completed:
                        options.remove(option)
                field['options'] = options
            req.hdf['newticket.fields.' + name] = field

        if req.perm.has_permission('TICKET_APPEND'):
            req.hdf['newticket.can_attach'] = True
            req.hdf['newticket.attachment'] = req.args.get('attachment')

        add_stylesheet(req, 'common/css/ticket.css')
        return 'newticket.cs', None





then later in the file defined the call to the above method as

            elif req.args.has_key('clone'):
                self.clone_request(req, db)

                # Use user supplied values
                ticket.populate(req.args)
                req.hdf['ticket.action'] = action
                req.hdf['ticket.ts'] = req.args.get('ts')
                req.hdf['ticket.reassign_owner'] = req.args.get('reassign_owner') \
                                                   or req.authname
                req.hdf['ticket.resolve_resolution'] = req.args.get('resolve_resolution')
                comment = req.args.get('comment')
                if comment:
                    req.hdf['ticket.comment'] = comment
                    # Wiki format a preview of comment
                    req.hdf['ticket.comment_preview'] = wiki_to_html(
                        comment, self.env, req, db)
                self._do_save(req, db, ticket)


I'm sure there are better ways to take advantage of Plugins but this was the fastest way for me to get this done.

  Changed 21 months ago by cboos

  • owner changed from jonas to cboos
  • status changed from reopened to new

I'm sure there are better ways to take advantage of Plugins but this was the fastest way for me to get this done.

You should preferably produce a patch for this change, that way others can easily take benefit from your work (do a svn checkout of the SubversionRepository, make you changes there, then at the top-level of the checkout, do svn diff > ticket_cloning_for_trac-0.10.patch).

For 0.11, I think we can come up with a simpler solution, I'll try to post one for comments a bit later on.

  Changed 21 months ago by nkantrowitz

Just thought it was worth mentioning that the Datamover plugin can copy tickets both between envs and within the same env.

  Changed 19 months ago by cboos

  • status changed from new to closed
  • resolution set to fixed
  • milestone changed from 1.0 to 0.11

Implemented in r5457.

  Changed 19 months ago by ThurnerRupert

  • status changed from closed to reopened
  • resolution fixed deleted

could you pls make this available to any user, not only admin? for trying to use this as "ticket template" (see #4044) it is essential.

allow reopen pls ...

  Changed 19 months ago by cboos

Ah, you're right. Then perhaps we could make use of a new permission here, or a configuration setting.

follow-up: ↓ 20   Changed 19 months ago by cboos

A TICKET_CLONE permission seems the most appropriate thing, then depending on the expected usage, the trac admin can grant that permission to anonymous, authenticated, or any other combination.

There's also some discussion going on about the placement of this "Clone" button. Some options are:

  • leave it like it is, in the ticket box
  • move it alongside with the other "actions" (which IMO should better be kept focused on the workflow related changes)
  • move it at the bottom of the page, next to the "Preview" and "Submit" ones, at the right side of the screen

I'd be interested to get feedback from future users of this feature.

Changed 19 months ago by cboos

Yet another possibility, the "clone" as an action distinct from the ones modifying the ticket itself

follow-up: ↓ 19   Changed 19 months ago by cboos

coderanger prototyped the attachment:clone_as_action.png alternative, which also has implications in the ITicketActionController API that would essentially allow to integrate those clone and delete operations in the upcoming bulk editor (#525).

  Changed 19 months ago by ThurnerRupert

ad ticket_clone permission: please not

i'm wondering what the gain would be. either you are allowed to create a new ticket or not, no matter where you get it from. and you are allowed to view a ticket or not. if you have both you are able to clone. but its very well possible i'm overlooking something. i'd prefer if trac could stay as slim as possible = asap :)

position of clone

i like the position where it currently is, beside the reply, as it is on top and saves us from scrolling down. even the delete should go, a very good idea of coderanger. but i would not mind it on the bottom additionally if somebody insists all the actions should stay there.

what we really miss on the bottom is the "next - previous" link, as we often have queries, edit one ticket, go to next, edit, go to next, edit ... and so on. currently this is a scrolling exercise.

or, what i personally find even more attractive, turn the order upside down, as it is with roundup, see http://www.selenic.com/mercurial/bts/issue552. this would leave all the links, buttons, editable fields in front of your nose, just the "old" things down.

but what i find counter-intuitive on the png (clone as action) is the two clicks you are forcing, as only one is necessary. you do not change and clone or change and delete at the same time, and then applying it. so i guess its against good ui design principles.

we plan to create some open tickets with contents (e.g. headlines, prio, type, etc filled out), mark it somehow (maybe keyword) to present it in a query/list. how we get this list behind the "new" i'm not sure yet - but maybe having a page with the link would be sufficient. or how we could get a clone icon in every line of the list ...

in reply to: ↑ 17   Changed 19 months ago by eblot

Replying to cboos:

coderanger prototyped the attachment:clone_as_action.png alternative, which also has implications in the ITicketActionController API that would essentially allow to integrate those clone and delete operations in the upcoming bulk editor (#525).

I'm really not a big fan of seeing Trac UI becoming a little bit more like too many other bug tracking tools that exhibit far too many fields and buttons. I initially chose Trac because of its clean and lean UI, and I hope it will stay simple.
Why not keeping the current style (as with the th:wiki:TicketDeletePlugin), that would be "Reply Delete" in the yellow box?

Having a ticket UI that involves scrolling to reach the numerous fields does not sound like user friendly... Keep in mind something essential: the more buttons and fields are shown, the less the people who want to fill in a bug.

Features that are rarely used (such as deleting a ticket) should not clutter the whole UI, even for the admin accounts.

in reply to: ↑ 16 ; follow-up: ↓ 21   Changed 19 months ago by ecarter

Replying to cboos:

A TICKET_CLONE permission seems the most appropriate thing, then depending on the expected usage, the trac admin can grant that permission to anonymous, authenticated, or any other combination.

Agreed. In my case, we have people who want the clone functionality who aren't ticket admins.

in reply to: ↑ 20 ; follow-up: ↓ 22   Changed 19 months ago by ThurnerRupert

Replying to ecarter:

Replying to cboos:

A TICKET_CLONE permission seems the most appropriate thing, then depending on the expected usage, the trac admin can grant that permission to anonymous, authenticated, or any other combination.

Agreed. In my case, we have people who want the clone functionality who aren't ticket admins.

would it not be sufficient to be allowed to have ticket create? i.e. no additional right necessary? for displaying the ticket itself, ticket read of course is necessary.

in reply to: ↑ 21 ; follow-up: ↓ 23   Changed 19 months ago by ecarter

Replying to ThurnerRupert:

would it not be sufficient to be allowed to have ticket create? i.e. no additional right necessary? for displaying the ticket itself, ticket read of course is necessary.

Well, yes... and no. On the one hand, ticket cloning is just creating a ticket. On the otherhand, it's a fast way to create a ticket. For internal systems, that's not a problem, but for public-facing sites, that could become a nuisance. But, adding TICKET_CLONE does increase the complexity of the system. Hmm... and you can already pre-fill fields via the url when you just have ticket create... so... maybe TICKET_CREATE should be all we check. I'm undecided.

in reply to: ↑ 22   Changed 19 months ago by cboos

Replying to ecarter:

Replying to ThurnerRupert:

would it not be sufficient to be allowed to have ticket create? i.e. no additional right necessary? for displaying the ticket itself, ticket read of course is necessary.

... I'm undecided.

Yes, I think it's a matter of local policy, and if there must be a "one size fits all", then we'd rather go in the direction pointed out by eblot: "clean and lean UI, ... hope it will stay simple."

That's admittedly not an easy goal to fulfill when you're adding features, but we should strive to it ;-)

Introducing a TICKET_CLONE permission is somewhat abusing the permission system in order to be able to adapt the UI to the expected "role" of the user. It's probably not the "best" way to do it, but the more flexible given the tools at hand. Maybe a special naming of the permission would help here, showing that it's more a capability than a permission? (e.g. ticket_clone_control)

  Changed 18 months ago by cboos

  • status changed from reopened to closed
  • resolution set to fixed
  • milestone changed from 0.11.1 to 0.11

Ok, for now we're already checking for TICKET_CREATE, so I think the "ticket duplication" can be considered to be implemented.

This doesn't mean it can't be improved upon in the next releases:

  • for the presentation point of view (though there seems to be more people liking the current way than the alternatives)
  • regarding (ab)using the permission system as a way to configure the UI (e.g. use something like TICKET_clone_operation - can't be all lower case as suggested in comment:23)

  Changed 14 months ago by cboos

  • status changed from closed to reopened
  • resolution fixed deleted

As discussed on trac-dev, I'll try to make a ITemplateStreamFilter sample plugin out of this.

  Changed 13 months ago by cboos

  • status changed from reopened to closed
  • resolution set to fixed

With r6153, this feature is now available as a single file plugin. Install by copying source:trunk/sample-plugins/ticket_clone.py in your <env>/plugins folder.

  Changed 2 months ago by anonymous

  • type changed from enhancement to defect

  Changed 2 months ago by anonymous

  • type changed from defect to enhancement

Add/Change #4686 (Ticket duplication using Trac)

Author



Change Properties
<Author field>
Action
as closed
Next status will be 'reopened'
to The owner will change from cboos. Next status will be 'closed'
 
Note: See TracTickets for help on using tickets.