DivideTicketIntoSubtasks
Comments0this wiki
HomePage > Contributions > DivideTicketIntoSubtasks
Contents |
DivideTicketIntoSubtasks
Edit
Often, we have a whole list of related tasks, and wish to create separate tickets for them all at once, perhaps for different people to work on. With these scrips You can do so through the use of bulleted list in the body of the initial ticket.
Original
Edit
This scrip action creates tickets for each list item for each task the main ticket DependsOn. It handles lists with dash or asterisk bullets:
* thingy 1 - thingy 2
Scrip Fields
Edit
Description: Split and link sub-tasks Condition: OnCreate Action: User Defined Template: Blank Stage: TransactionCreate #With modern RTs You may need to use TransactionBatch instead.
Action preparation code
Edit
require MIME::Entity;
my $trans = $self->TransactionObj;
my $tkt = $self->TicketObj;
my $cont = $trans->Content;
my $requestors = [ $tkt->Requestors->MemberEmailAddresses ];
#Updated to require whitespace between bullet & entry
if ($cont =~ m/^\s*[-*]\s/m) {
$cont =~ s/^\n.*//sm;
my @lines = split(/[\n\r]*^\s*[-*]\s+/m, $cont); #update
shift(@lines);
foreach my $line (@lines) {
my $new_tkt = RT::Ticket->new($RT::SystemUser);
my ($id, $msg) = $new_tkt->Create(
Queue => "General",
Subject => $line,
Status => 'new',
Requestor => $requestors,
DependedOnBy => $tkt->Id,
MIMEObj => MIME::Entity->build(
Type => 'text/plain',
Data => $line));
}
}
return 1;
Action cleanup code
Edit
return 1;
New Variant (2)
Edit
The version below handles nested bulleted lists, and the bullet character indicates the link relationship, as defied in %links. Note that this scrip will not fire if the bulleted list is preceded by other content.
*starfruit * apple @@ gala ++ fuji @ melons ** watermelon *** stars & stripes **cantaloupe
This update of the initial revision also handles signatures, long items entered via the UI, and fixes a conflict with HideTransactions.
Action preparation code
Edit
require MIME::Entity; require Text::Wrap;
#Semi-configurable items, see also 5.10 @ Unwrap below
local $Text::Wrap::columns = 64;
#You probably don't want to use '#' without modifying the truncated entry comment char
my %links = ('*' => 'DependedOnBy', '+' => 'Parents', '@' => 'RefersTo');
#Preparation
my $tkt = $self->TicketObj;
my $cont = $self->TransactionObj->Content;
my $requestors = [ $tkt->Requestors->MemberEmailAddresses ];
my $sym = qr/[\Q@{[join '', keys %links]}\E]/;
#Strip leading comments, e.g; untruncated entry
$cont =~ s/^\s*(#[^\n]+\n)+\n?//s;
#Strip signature
$cont =~ s/^-- \n.+$//m;
#Unwrap long lines from RT's hard-wrap textareas, use the one matching your perl
#1 while $cont =~ s/^\s*$sym\s*[^\n]+\K\n(?!^$sym)/ /m; #5.10
1 while $cont =~ s/^(\s*$sym\s*[^\n]+)\n(?!^$sym)/$1 /m; #5.8
#Parse bullets
while( $cont =~ /\G\s*($sym)\s*([^\n]+)((?:\s*$sym{2,}\s*[^\n]+)+)?/mg ){
my($link, $subj, $body) = ($1, $2, $3||'');
$body =~ s/^$sym//mg if length($body);
#Wrap our long item into a body comment before truncating
if( length($subj) > $Text::Wrap::columns ){
$body = Text::Wrap::wrap('# ', '# ', $subj) . "\n" . $body;
my($under, $over) = ($Text::Wrap::columns-5, $Text::Wrap::columns+5);
$subj =~ /(.{$under,$over}(?<!\s)\b)|(.{$Text::Wrap::columns})/;
$subj = $1 ? "$1..." : ($2||$subj);
}
#$RT::SystemUser would not play nice with HideTransactions
my $new_tkt = RT::Ticket->new($RT::Nobody);
my ($id, $msg) = $new_tkt->Create(
Queue => "TODO",
Subject => $subj,
Status => 'new',
Owner => $tkt->Owner,
Requestor => $requestors,
$links{$link} => $tkt->Id,
MIMEObj => MIME::Entity->build(Data => $body)
);
}
return 1;
Nested Subtickets Variant 3
Edit
I had problems with Variant 2 in RT 3.8 and I wanted something a little simpler that would created nested subtickets. It does not use the MIME::Entity module since I don't want to put a default comment in the subtickets.
This creates DependsOn links with either * or - symbols. Create sublinks by adding *'s or -'s.
Example:
*Level 1 **Level 1-1 **Level 1-1 ***Level 1-1-1 *Level 2 ** Level 2-1 * Level 3 **Level 3-1
Action Preparation Code:
my $trans = $self->TransactionObj;
my $tkt = $self->TicketObj;
my $cont = $trans->Content;
my $requestors = [ $tkt->Requestors->MemberEmailAddresses ];
if ($cont =~ m/^\s*[\*-]+/m) {
my %tickets;
foreach (split(/[\n\r]/, $cont)) {
#Split number of *'s and actual subject.
next unless /^\s*([\*-]+)(.+)$/;
next unless $2;
my $lvl = $1; my $value=$2;
#Count the number of *'s
my $count = scalar split //, $lvl;
#Keep track of the tickets' parents
$tickets{$count}=[$value];
#One line is one ticket
my $new_tkt = RT::Ticket->new($RT::SystemUser);
#If there is a parent ticket create dependencies on it
if (exists $tickets{$count-1}) {
my ($id, $msg) = $new_tkt->Create(
Queue => $tkt->Queue,
Subject => $value,
Status => 'new',
Requestor => $requestors,
Owner => $tkt->Owner,
DependedOnBy => $tickets{$count-1}[1],
);
#Store ticket id for children
push @{$tickets{$count}}, $id;
#If no parent ticket, create dependencies on the new ticket
} else {
my ($id, $msg) = $new_tkt->Create(
Queue => $tkt->Queue,
Subject => $value,
Status => 'new',
Requestor => $requestors,
Owner => $tkt->Owner,
DependedOnBy => $tkt->Id,
);
#Store ticket id for children
push @{$tickets{$count}}, $id;
#Die if we got here without recording the parent somehow
return 0 if $count > 1;
}
}
}
return 1;