diff --git a/html/AssetTracker/Asset/Clone.html b/html/AssetTracker/Asset/Clone.html
new file mode 100644
index 000000000..2e8a12ae0
--- /dev/null
+++ b/html/AssetTracker/Asset/Clone.html
@@ -0,0 +1,70 @@
+<& /Elements/Header,
+ Title => $AssetObj->Name &>
+<& /Elements/Tabs &>
+
+<& /Elements/ListActions, actions => \@Actions &>
+
+<& /Elements/TitleBoxStart, title => loc('New Asset'), color=> "#333399", contentbg => '#ffffff' &>
+
+
+<& /Elements/TitleBoxEnd &>
+
+
+
+<& /Elements/TitleBoxStart, title => loc('Cloning Asset'), contentbg => '#bbbbbb' &>
+<& /AssetTracker/Asset/Elements/ShowBasics, Asset => $AssetObj &>
+<& /Elements/TitleBoxEnd &>
+
+<%ARGS>
+$id => undef
+$Create => undef
+$AssetObj => undef
+$Actions => undef
+$Name => undef
+%ARGS>
+
+<%INIT>
+
+$m->comp('/Elements/Callback', _CallbackName => 'Initial', AssetObj => $AssetObj, ARGSRef => \%ARGS);
+
+my ($linkid, $message, @Actions, $tid, $Assets);
+push(@Actions, @$Actions) if $Actions;
+
+unless ($id || $AssetObj) {
+ Abort('No asset specified');
+}
+
+if (!$AssetObj) {
+
+ $AssetObj = RTx::AssetTracker::Asset->new($session{'CurrentUser'});
+
+ $AssetObj = LoadAsset($ARGS{'id'});
+ unless ($AssetObj->CurrentUserHasRight('ShowAsset')) {
+ Abort("No permission to view asset");
+ }
+}
+
+if ($ARGS{'new'} eq 'new') {
+ unless ($AssetObj->CurrentUserHasRight('CreateAsset')) {
+ Abort('You have no permission to create assets of that type.');
+ }
+ my ($rv, $trans, $msg) = $AssetObj->Clone($Name);
+ if ($rv) {
+ $m->redirect("Display.html?id=$rv");
+ }
+ else {
+ push (@Actions, $msg);
+ }
+}
+
+$m->comp('/Elements/Callback', _CallbackName => 'BeforeDisplay',
+ AssetObj => \$AssetObj, Assets => \$Assets, ARGSRef => \%ARGS);
+
+%INIT>
diff --git a/html/AssetTracker/Asset/Create.html b/html/AssetTracker/Asset/Create.html
index 64478d720..2a6bb206a 100644
--- a/html/AssetTracker/Asset/Create.html
+++ b/html/AssetTracker/Asset/Create.html
@@ -104,7 +104,6 @@
% $m->callback( CallbackName => 'AfterRoles', ARGSRef => \%ARGS );
<& /AssetTracker/Asset/Elements/EditCustomFields, %ARGS, TypeObj => $TypeObj, InTable => 1 &>
-%# <& /AssetTracker/Asset/Elements/EditTransactionCustomFields, %ARGS, TypeObj => $TypeObj, InTable => 1 &>
&>
% $m->callback( CallbackName => 'AfterBasics', TypeObj => $TypeObj, ARGSRef => \%ARGS );
@@ -142,79 +141,6 @@
my %link_types = %{ RTx::AssetTracker::Asset::LINKTYPEMAP() };
my @link_order = RTx::AssetTracker::Asset::LINKORDER();
-if ($CloneAsset) {
- my $CloneAssetObj = RTx::AssetTracker::Asset->new( $session{CurrentUser} );
- $CloneAssetObj->Load($CloneAsset)
- or Abort( loc("Asset could not be loaded") );
-
- my $clone = { };
-
- foreach my $role ( $CloneAssetObj->TypeObj->RoleGroupTypes() ) {
- my $role_method = $role . 'RoleGroup';
- $clone->{$role} = join( ',', $CloneAssetObj->$role_method->MemberEmailAddressesAsString );
- }
-
- $clone->{$_} = $CloneAssetObj->$_()
- for qw/Name Description Status/;
-
- if (0) { # Temporarily disabled
- my $members = $CloneAssetObj->Members;
- my ( @members, @members_of, @refers, @refers_by, @depends, @depends_by );
- my $refers = $CloneAssetObj->RefersTo;
- while ( my $refer = $refers->Next ) {
- push @refers, $refer->LocalTarget;
- }
- $clone->{'new-RefersTo'} = join ' ', @refers;
-
- my $refers_by = $CloneAssetObj->ReferredToBy;
- while ( my $refer_by = $refers_by->Next ) {
- push @refers_by, $refer_by->LocalBase;
- }
- $clone->{'RefersTo-new'} = join ' ', @refers_by;
- my $depends = $CloneAssetObj->DependsOn;
- while ( my $depend = $depends->Next ) {
- push @depends, $depend->LocalTarget;
- }
- $clone->{'new-DependsOn'} = join ' ', @depends;
-
- my $depends_by = $CloneAssetObj->DependedOnBy;
- while ( my $depend_by = $depends_by->Next ) {
- push @depends_by, $depend_by->LocalBase;
- }
- $clone->{'DependsOn-new'} = join ' ', @depends_by;
-
- while ( my $member = $members->Next ) {
- push @members, $member->LocalBase;
- }
- $clone->{'MemberOf-new'} = join ' ', @members;
-
- my $members_of = $CloneAssetObj->MemberOf;
- while ( my $member_of = $members_of->Next ) {
- push @members_of, $member_of->LocalTarget;
- }
- $clone->{'new-MemberOf'} = join ' ', @members_of;
-
- }
-
- my $cfs = $CloneAssetObj->TypeObj->AssetCustomFields();
- while ( my $cf = $cfs->Next ) {
- my $cf_id = $cf->id;
- my $cf_values = $CloneAssetObj->CustomFieldValues( $cf->id );
- my @cf_values;
- while ( my $cf_value = $cf_values->Next ) {
- push @cf_values, $cf_value->Content;
- }
- $clone->{"Object-RTx::AssetTracker::Asset--CustomField-$cf_id-Value"} = join "\n",
- @cf_values;
- }
-
- $clone->{'ChangeComment'} = "Cloned from asset #$CloneAsset.";
-
- for ( keys %$clone ) {
- $ARGS{$_} = $clone->{$_} if not defined $ARGS{$_};
- }
-}
-
my @results;
my $title = loc("Create a new asset");
@@ -256,5 +182,5 @@
%INIT>
<%ARGS>
-$CloneAsset => undef
+
%ARGS>
diff --git a/html/Callbacks/AssetTracker/Elements/Tabs/Privileged b/html/Callbacks/AssetTracker/Elements/Tabs/Privileged
index 82480502d..84ae4c2de 100644
--- a/html/Callbacks/AssetTracker/Elements/Tabs/Privileged
+++ b/html/Callbacks/AssetTracker/Elements/Tabs/Privileged
@@ -67,6 +67,7 @@ if ( $request_path =~ m{^/AssetTracker/} ) {
if ( $can->('ModifyAsset') ) {
$tabs->child( fields => title => loc('Fields'), path => "/AssetTracker/Asset/ModifyFields.html?id=" . $id, );
$tabs->child( links => title => loc('Links'), path => "/AssetTracker/Asset/ModifyLinks.html?id=" . $id, );
+ $tabs->child( clone => title => loc('Clone'), path => "/AssetTracker/Asset/Clone.html?id=" . $id, );
}
#if ( $can->('ModifyAsset') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
diff --git a/lib/RTx/AssetTracker/Asset.pm b/lib/RTx/AssetTracker/Asset.pm
index 407f5cc93..7109d1c03 100644
--- a/lib/RTx/AssetTracker/Asset.pm
+++ b/lib/RTx/AssetTracker/Asset.pm
@@ -494,6 +494,36 @@ sub Create {
}
}
+sub Clone {
+
+ # still need to handle Links
+ my $self = shift;
+ my $name = shift or return ( 0, 0, "No name specified for cloned asset." );
+
+ # test name uniqueness
+ my ($rv, $msg) = $self->SatisfiesUniqueness($name, $self->TypeObj->Id, $self->Status);
+ return ($rv, 0, $msg) unless $rv;
+
+ my @CustomFields;
+ my $cfs = $self->CustomFields;
+ while (my $cf = $cfs->Next) {
+ # may have to skip unique CFs some day
+ push @CustomFields, "CustomField-" . $cf->Id;
+
+ my $cfvals = $self->CustomFieldValues($cf->Id);
+ push @CustomFields, [ map { $_->Content } @{$cfvals->ItemsArrayRef} ];
+ }
+
+ my $asset = RTx::AssetTracker::Asset->new($self->CurrentUser);
+ return $asset->Create(
+ Type => $self->TypeObj,
+ Name => $name,
+ Description => $self->Description,
+ Status => $self->Status,
+ TransactionData => "Cloned from " . $self->Name,
+ @CustomFields );
+}
+
sub _AddLinksOnCreateOrUpdate {
my ($self, %args) = @_;