Skip to content

Commit 3679823

Browse files
committed
Support to update maps of a lifecycle via JSON on Advanced page
1 parent 7292690 commit 3679823

File tree

3 files changed

+145
-4
lines changed

3 files changed

+145
-4
lines changed

lib/RT/Lifecycle.pm

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,27 +1005,34 @@ sub UpdateLifecycle {
10051005
return (1, $CurrentUser->loc("Lifecycle [_1] updated", $name));
10061006
}
10071007

1008-
=head2 UpdateMaps( CurrentUser => undef, Maps => undef )
1008+
=head2 UpdateMaps( CurrentUser => undef, Maps => undef, Name => undef )
10091009
10101010
Update lifecycle maps.
10111011
10121012
Returns (STATUS, MESSAGE). STATUS is true if succeeded, otherwise false.
10131013
1014+
Note that the Maps in argument will be merged into existing maps. To delete
1015+
all existing items for a lifecycle before merging, pass its Name.
1016+
10141017
=cut
10151018

10161019
sub UpdateMaps {
10171020
my $class = shift;
10181021
my %args = (
10191022
CurrentUser => undef,
10201023
Maps => undef,
1024+
Name => undef,
10211025
@_,
10221026
);
10231027

10241028
my $CurrentUser = $args{CurrentUser};
10251029
my $lifecycles = RT->Config->Get('Lifecycles');
10261030

1031+
my $all_maps = $lifecycles->{__maps__} || {};
1032+
my @keep_keys = grep { $args{Name} && !/^\Q$args{Name}\E -> | -> \Q$args{Name}\E$/ } keys %$all_maps;
1033+
10271034
%{ $lifecycles->{__maps__} } = (
1028-
%{ $lifecycles->{__maps__} || {} },
1035+
map( { $_ => $all_maps->{$_} } @keep_keys ),
10291036
%{ $args{Maps} },
10301037
);
10311038

share/html/Admin/Lifecycles/Advanced.html

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@
5454
</span>
5555
</div>
5656

57-
<form action="<%RT->Config->Get('WebPath')%>/Admin/Lifecycles/Advanced.html" name="ModifyLifecycleAdvanced" method="post" enctype="multipart/form-data" class="mx-auto max-width-sm">
57+
58+
<form action="<%RT->Config->Get('WebPath')%>/Admin/Lifecycles/Advanced.html" name="ModifyLifecycleAdvanced" method="post" enctype="multipart/form-data" class="mx-auto max-width-lg">
5859
<input type="hidden" class="hidden" name="Name" value="<% $LifecycleObj->Name %>" />
5960
<input type="hidden" class="hidden" name="Type" value="<% $LifecycleObj->Type %>" />
60-
61+
<&| /Widgets/TitleBox, title => loc('Basics'), content_class => 'mx-auto width-sm' &>
6162
<div class="form-row">
6263
<span class="col-12">
6364
<textarea class="form-control" rows="30" name="Config"><% $Config |n %></textarea>
@@ -83,8 +84,40 @@
8384
<& /Elements/Submit, Label => loc('Delete'), Name => 'Delete' &>
8485
</div>
8586
</div>
87+
</&>
8688
</form>
8789

90+
91+
92+
<form action="<%RT->Config->Get('WebPath')%>/Admin/Lifecycles/Advanced.html" name="ModifyLifecycleAdvancedMappings" method="post" enctype="multipart/form-data" class="mx-auto max-width-lg">
93+
<input type="hidden" class="hidden" name="Name" value="<% $LifecycleObj->Name %>" />
94+
<input type="hidden" class="hidden" name="Type" value="<% $LifecycleObj->Type %>" />
95+
<&| /Widgets/TitleBox, title => loc('Mappings'), content_class => 'mx-auto width-sm' &>
96+
97+
<div class="form-row">
98+
<span class="col-12">
99+
<textarea class="form-control" rows="30" name="Maps"><% $Maps |n %></textarea>
100+
</span>
101+
</div>
102+
103+
<div class="form-row invalid-json hidden">
104+
<div class="col-12">
105+
<div class="alert alert-danger mb-0"><&|/l&>Invalid JSON</&></div>
106+
</div>
107+
</div>
108+
109+
<div class="form-row">
110+
<div class="col-6 d-flex">
111+
<& /Elements/Submit, Label => loc('Validate Mappings'), Name => 'ValidateMaps' &>
112+
</div>
113+
<div class="col-6">
114+
<& /Elements/Submit, Label => loc('Save Mappings'), Name => 'UpdateMaps' &>
115+
</div>
116+
</div>
117+
</&>
118+
</form>
119+
120+
88121
<%INIT>
89122
my ($title, @results);
90123
my $LifecycleObj = RT::Lifecycle->new();
@@ -100,6 +133,13 @@
100133
push @results, loc("The graphical lifecycle builder is not currently supported on IE 11. You can update the lifecycle configuration using the Advanced tab or access the lifecycle editor in a supported browser.");
101134
}
102135

136+
if ( !defined $Maps && ( my $all_maps = RT->Config->Get('Lifecycles')->{__maps__} ) ) {
137+
for my $item ( grep {/^\Q$Name\E -> | -> \Q$Name\E$/} keys %$all_maps ) {
138+
$Maps->{$item} = $all_maps->{$item};
139+
}
140+
$Maps = JSON::to_json( $Maps || {}, { canonical => 1, pretty => 1 } );
141+
}
142+
103143
my $redirect_to ='/Admin/Lifecycles/Advanced.html';
104144
my %redirect_args;
105145

@@ -157,6 +197,41 @@
157197
);
158198
}
159199
}
200+
elsif ( $ValidateMaps || $UpdateMaps ) {
201+
my $maps = JSON::from_json($Maps || '{}');
202+
203+
my ( $valid, @warnings )
204+
= $LifecycleObj->ValidateLifecycleMaps( Maps => $maps, CurrentUser => $session{CurrentUser} );
205+
206+
my $updated;
207+
if ($valid) {
208+
if ($ValidateMaps) {
209+
push @results, loc('Mappings is valid');
210+
}
211+
else {
212+
# Maps will be merged into existing value, here we remove existing values so admins can delete items
213+
214+
( $updated, my $msg ) = RT::Lifecycle->UpdateMaps(
215+
CurrentUser => $session{CurrentUser},
216+
Maps => $maps,
217+
Name => $Name,
218+
);
219+
push @results, $msg;
220+
}
221+
222+
}
223+
else {
224+
push @results, @warnings;
225+
}
226+
227+
%redirect_args = (
228+
Name => $Name,
229+
Type => $Type,
230+
231+
# Get the latest canonicalized data if updated successfully
232+
$updated ? () : ( Maps => $Maps ),
233+
);
234+
}
160235

161236
MaybeRedirectForResults(
162237
Actions => \@results,
@@ -172,4 +247,7 @@
172247
$Validate => undef
173248
$Update => undef
174249
$Delete => undef
250+
$ValidateMaps => undef
251+
$UpdateMaps => undef
252+
$Maps => undef
175253
</%ARGS>

t/web/lifecycle_mappings.t

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,62 @@ diag "Test updating sales-engineering mappings";
172172
);
173173
}
174174

175+
diag "Test advanced mappings";
176+
{
177+
$m->get_ok( $url . '/Admin/Lifecycles/Advanced.html?Type=ticket&Name=sales-engineering' );
178+
my $form = $m->form_name('ModifyLifecycleAdvancedMappings');
179+
180+
require JSON;
181+
my $maps = JSON::from_json( $form->value('Maps') );
182+
is_deeply(
183+
$maps,
184+
{
185+
'sales-engineering -> default' => {
186+
'rejected' => 'rejected',
187+
'resolved' => 'resolved',
188+
'deleted' => 'deleted',
189+
'engineering' => 'open',
190+
'stalled' => 'stalled',
191+
'sales' => 'new'
192+
}
193+
},
194+
'Correct current value'
195+
);
196+
197+
$maps->{'default -> sales-engineering'} = { 'new' => 'sales', };
198+
199+
$m->submit_form_ok(
200+
{
201+
fields => {
202+
Maps => JSON::to_json($maps),
203+
Name => "sales-engineering",
204+
Type => "ticket",
205+
},
206+
button => 'UpdateMaps',
207+
},
208+
'Update maps'
209+
);
210+
$m->content_contains('Lifecycle mappings updated');
211+
$form = $m->form_name('ModifyLifecycleAdvancedMappings');
212+
is_deeply( $maps, JSON::from_json( $form->value('Maps') ), 'Correct updated value' );
213+
214+
$m->submit_form_ok(
215+
{
216+
fields => {
217+
Maps => '',
218+
Name => "sales-engineering",
219+
Type => "ticket",
220+
},
221+
button => 'UpdateMaps',
222+
},
223+
'Clear maps'
224+
);
225+
$m->content_contains('Lifecycle mappings updated');
226+
$form = $m->form_name('ModifyLifecycleAdvancedMappings');
227+
$form->value( "Maps", "{}", 'Maps got cleared' );
228+
}
229+
230+
175231
sub reload_lifecycle {
176232
# to get rid of the warning of:
177233
# you're changing config option in a test file when server is active

0 commit comments

Comments
 (0)