2 package SGN
::Controller
::AJAX
::List
;
6 use List
::MoreUtils qw
| uniq
|;
10 use CXGN
::List
::Validate
;
11 use CXGN
::List
::Transform
;
12 use CXGN
::List
::FuzzySearch
;
13 use CXGN
::List
::Desynonymize
;
17 BEGIN { extends
'Catalyst::Controller::REST'; }
20 default => 'application/json',
22 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
25 sub get_list_action
:Path
('/list/get') Args
(0) {
29 my $list_id = $c->req->param("list_id");
31 my $user_id = $self->get_user($c);
33 $c->stash->{rest
} = { error
=> 'You must be logged in to use lists.', };
37 my $list = $self->retrieve_list($c, $list_id);
39 $c->stash->{rest
} = $list;
42 sub get_list_data_action
:Path
('/list/data') Args
(0) {
46 my $list_id = $c->req->param("list_id");
48 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
49 my $public = $list->check_if_public();
51 my $error = $self->check_user($c, $list_id);
53 $c->stash->{rest
} = { error
=> $error };
58 $list = $self->retrieve_list($c, $list_id);
60 my $metadata = $self->get_list_metadata($c, $list_id);
64 type_id
=> $metadata->{type_id
},
65 type_name
=> $metadata->{list_type
},
71 sub retrieve_contents
:Path
('/list/contents') Args
(1) {
76 my $list = CXGN
::List
->new( { dbh
=>$c->dbc->dbh(), list_id
=>$list_id });
77 my $public = $list->check_if_public();
79 my $error = $self->check_user($c, $list_id);
81 $c->stash->{rest
} = { error
=> $error };
86 my $elements = $list->elements();
87 $c->stash->{rest
} = $elements;
90 sub get_list_metadata
{
95 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh(), list_id
=>$list_id });
97 return { name
=> $list->name(),
98 description
=> $list->description(),
99 type_id
=> $list->type_id(),
100 list_type
=> $list->type(),
104 sub get_type_action
:Path
('/list/type') Args
(1) {
109 my $data = $self->get_list_metadata($c, $list_id);
111 $c->stash->{rest
} = { type_id
=> $data->{type_id
},
112 list_type
=> $data->{list_type
},
116 sub update_list_name_action
:Path
('/list/name/update') :Args
(0) {
119 my $list_id = $c->req->param('list_id');
120 my $name = $c->req->param('name');
122 my $user_id = $self->get_user($c);
123 my $error = $self->check_user($c, $list_id);
126 $c->stash->{rest
} = { error
=> $error };
130 my $list = CXGN
::List
->new( { dbh
=>$c->dbc->dbh(), list_id
=>$list_id });
132 $error = $list->name($name);
135 $c->stash->{rest
} = { error
=> $error };
139 $c->stash->{rest
} = { success
=> 1 };
142 sub set_type
:Path
('/list/type') Args
(2) {
148 my $user_id = $self->get_user($c);
150 my $error = $self->check_user($c, $list_id);
152 $c->stash->{rest
} = { error
=> $error };
156 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh(), list_id
=> $list_id });
158 if ($list->owner() != $user_id) {
159 $c->stash->{rest
} = { error
=> "Only the list owner can change the type of a list" };
163 $error = $list->type($type);
166 $c->stash->{rest
} = { error
=> "List type not found: ".$type };
170 $c->stash->{rest
} = { success
=> 1 };
173 sub new_list_action
:Path
('/list/new') Args
(0) {
177 my $name = $c->req->param("name");
178 my $desc = $c->req->param("desc");
181 my $user_id = $self->get_user($c);
183 $c->stash->{rest
} = { error
=> "You must be logged in to use lists", };
189 $new_list_id = $self->new_list($c, $name, $desc, $user_id);
193 $c->stash->{rest
} = { error
=> "An error occurred, $@", };
197 $c->stash->{rest
} = { list_id
=> $new_list_id };
201 sub all_types
: Path
('/list/alltypes') :Args
(0) {
205 my $all_types = CXGN
::List
::all_types
($c->dbc->dbh());
207 $c->stash->{rest
} = $all_types;
210 sub download_list
:Path
('/list/download') Args
(0) {
213 my $list_id = $c->req->param("list_id");
215 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
216 my $public = $list->check_if_public();
218 my $error = $self->check_user($c, $list_id);
220 $c->res->content_type("text/plain");
221 $c->res->body($error);
226 $list = $self->retrieve_list($c, $list_id);
228 $c->res->content_type("text/plain");
229 $c->res->body(join "\n", map { $_->[1] } @
$list);
232 =head2 available_lists()
235 Desc: returns the available lists. Optionally, a
236 parameter "list_type" can be provided that will limit the
237 lists to the provided type.
246 sub available_lists
: Path
('/list/available') Args
(0) {
250 my $requested_type = $c->req->param("type");
252 my $user_id = $self->get_user($c);
254 $c->stash->{rest
} = { error
=> "You must be logged in to use lists.", };
258 my $lists = CXGN
::List
::available_lists
($c->dbc->dbh(), $user_id, $requested_type);
260 $c->stash->{rest
} = $lists;
263 sub available_public_lists
: Path
('/list/available_public') Args
(0) {
267 my $requested_type = $c->req->param("type");
269 my $user_id = $self->get_user($c);
271 $c->stash->{rest
} = { error
=> "You must be logged in to use lists.", };
275 my $lists = CXGN
::List
::available_public_lists
($c->dbc->dbh(), $requested_type);
277 $c->stash->{rest
} = $lists;
280 sub add_item
:Path
('/list/item/add') Args
(0) {
284 my $list_id = $c->req->param("list_id");
285 my $element = $c->req->param("element");
287 my $user_id = $self->get_user($c);
289 my $error = $self->check_user($c, $list_id);
291 $c->stash->{rest
} = { error
=> $error };
295 $element =~ s/^\s*(.+?)\s*$/$1/;
298 $c->stash->{rest
} = { error
=> "You must provide an element to add to the list" };
303 $c->stash->{rest
} = { error
=> "Please specify a list_id." };
308 $self->insert_element($c, $list_id, $element);
311 $c->stash->{rest
} = { error
=> "An error occurred: $@" };
315 $c->stash->{rest
} = [ "SUCCESS" ];
319 sub toggle_public_list
: Path
('/list/public/toggle') Args
(0) {
322 my $list_id = $c->req->param("list_id");
324 my $error = $self->check_user($c, $list_id);
326 $c->stash->{rest
} = { error
=> $error };
330 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
331 my ($public, $rows_affected) = $list->toggle_public();
332 if ($rows_affected == 1) {
333 $c->stash->{rest
} = { r
=> $public };
339 sub make_public_list
: Path
('/list/public/true') Args
(0) {
342 my $list_id = $c->req->param("list_id");
344 my $error = $self->check_user($c, $list_id);
346 $c->stash->{rest
} = { error
=> $error };
350 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
351 my ($rows_affected) = $list->make_public();
352 if ($rows_affected == 1) {
353 $c->stash->{rest
} = { success
=>1 };
359 sub make_private_list
: Path
('/list/public/false') Args
(0) {
362 my $list_id = $c->req->param("list_id");
364 my $error = $self->check_user($c, $list_id);
366 $c->stash->{rest
} = { error
=> $error };
370 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
371 my ($rows_affected) = $list->make_private();
372 if ($rows_affected == 1) {
373 $c->stash->{rest
} = { success
=>1 };
379 sub copy_public_list
: Path
('/list/public/copy') Args
(0) {
382 my $list_id = $c->req->param("list_id");
384 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
385 my $public = $list->check_if_public();
386 my $user_id = $self->get_user($c);
387 if (!$user_id || $public == 0) {
388 $c->stash->{rest
} = { error
=> 'You must be logged in to use lists and list must be public!' };
392 my $copied = $list->copy_public($user_id);
394 $c->stash->{rest
} = { success
=> 'true' };
400 sub add_cross_progeny
: Path
('/list/add_cross_progeny') Args
(0) {
403 my $cross_id_list = decode_json
($c->req->param("cross_id_list"));
404 #print STDERR Dumper $cross_id_list;
405 my $list_id = $c->req->param("list_id");
407 my $list = CXGN
::List
->new( { dbh
=>$c->dbc->dbh(), list_id
=> $list_id });
410 $response{'count'} = 0;
411 foreach (@
$cross_id_list) {
412 my $cross = CXGN
::Cross
->new({bcs_schema
=>$c->dbic_schema("Bio::Chado::Schema"), cross_stock_id
=>$_});
413 my ($maternal_parent, $paternal_parent, $progeny) = $cross->get_cross_relationships();
416 foreach (@
$progeny) {
417 push @accession_names, $_->[0];
420 my $r = $list->add_bulk(\
@accession_names);
422 $c->stash->{rest
} = { error
=> $r->{error
}};
425 if (scalar(@
{$r->{duplicates
}}) > 0){
426 $response{'duplicates'} = $r->{duplicates
};
428 $response{'count'} += $r->{count
};
430 #print STDERR Dumper \%response;
431 $c->stash->{rest
} = { duplicates
=> $response{'duplicates'} };
432 $c->stash->{rest
}->{success
} = { count
=> $response{'count'} };
435 sub add_bulk
: Path
('/list/add/bulk') Args
(0) {
438 my $list_id = $c->req->param("list_id");
439 my $elements = $c->req->param("elements");
441 my $user_id = $self->get_user($c);
442 my $error = $self->check_user($c, $list_id);
444 $c->stash->{rest
} = { error
=> $error };
449 $c->stash->{rest
} = { error
=> "You must provide one or more elements to add to the list" };
453 my @elements = split "\t", $elements;
455 my $list = CXGN
::List
->new( { dbh
=>$c->dbc->dbh(), list_id
=> $list_id });
460 my $response = $list->add_bulk(\
@elements);
461 #print STDERR Dumper $response;
463 if ($response->{error
}) {
464 $c->stash->{rest
} = { error
=> $response->{error
}};
467 if (scalar(@
{$response->{duplicates
}}) > 0){
468 $c->stash->{rest
} = { duplicates
=> $response->{duplicates
} };
471 $c->stash->{rest
}->{success
} = $response->{count
};
474 sub insert_element
: Private
{
480 my $list = CXGN
::List
->new( { dbh
=>$c->dbc->dbh(), list_id
=> $list_id });
482 $list->add_element($element);
485 sub delete_list_action
:Path
('/list/delete') Args
(0) {
489 my $list_id = $c->req->param("list_id");
491 my $error = $self->check_user($c, $list_id);
493 $c->stash->{rest
} = { error
=> $error };
497 $error = CXGN
::List
::delete_list
($c->dbc->dbh(), $list_id);
500 $c->stash->{rest
} = { error
=> $error };
503 $c->stash->{rest
} = [ 1 ];
508 sub exists_list_action
: Path
('/list/exists') Args
(0) {
511 my $name = $c->req->param("name");
513 my $user_id = $self->get_user($c);
515 $c->stash->{rest
} = { error
=> 'You need to be logged in to use lists.' };
518 my $list_id = CXGN
::List
::exists_list
($c->dbc->dbh(), $name, $user_id);
521 $c->stash->{rest
} = { list_id
=> $list_id };
524 $c->stash->{rest
} = { list_id
=> undef };
528 sub exists_item_action
: Path
('/list/exists_item') :Args
(0) {
531 my $list_id = $c->req->param("list_id");
532 my $name = $c->req->param("name");
534 my $error = $self->check_user($c, $list_id);
536 $c->stash->{rest
} = { error
=> $error };
540 my $user_id = $self->get_user($c);
542 if ($self->get_list_owner($c, $list_id) != $user_id) {
543 $c->stash->{rest
} = { error
=> "You have insufficient privileges to manipulate this list.", };
547 my $list_item_id = $self->exists_item($c, $list_id, $name);
550 $c->stash->{rest
} = { list_item_id
=> $list_item_id };
553 $c->stash->{rest
} = { list_item_id
=> 0 };
557 sub list_size
: Path
('/list/size') Args
(0) {
560 my $list_id = $c->req->param("list_id");
562 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
563 my $count = $list->list_size();
565 $c->stash->{rest
} = { count
=> $count };
568 sub validate
: Path
('/list/validate') Args
(2) {
574 my $list = $self->retrieve_list($c, $list_id);
576 my @flat_list = map { $_->[1] } @
$list;
578 my $lv = CXGN
::List
::Validate
->new();
579 my $data = $lv->validate($c->dbic_schema("Bio::Chado::Schema"), $type, \
@flat_list);
581 $c->stash->{rest
} = $data;
584 sub fuzzysearch
: Path
('/list/fuzzysearch') Args
(2) {
588 my $list_type = shift;
590 my $list = $self->retrieve_list($c, $list_id);
592 my @flat_list = map { $_->[1] } @
$list;
594 my $f = CXGN
::List
::FuzzySearch
->new();
595 my $data = $f->fuzzysearch($c->dbic_schema("Bio::Chado::Schema"), $list_type, \
@flat_list);
597 $c->stash->{rest
} = $data;
600 sub transform
:Path
('/list/transform/') Args
(2) {
604 my $transform_name = shift;
606 my $t = CXGN
::List
::Transform
->new();
608 my $data = $self->get_list_metadata($c, $list_id);
610 my $list_data = $self->retrieve_list($c, $list_id);
612 my @list_items = map { $_->[1] } @
$list_data;
614 my $result = $t->transform($c->dbic_schema("Bio::Chado::Schema"), $transform_name, \
@list_items);
616 if (exists($result->{missing
}) && (scalar(@
{$result->{missing
}}) > 0)) {
617 $c->stash->{rest
} = { error
=> "This lists contains elements that cannot be converted. Not converting list.", };
621 $c->stash->{rest
} = $result;
625 sub replace_elements
:Path
('/list/item/replace') Args
(2) {
630 my $new_list = shift; # tab delimited new list elements
634 sub combine_lists
: Path
('/list/combine') Args
(2) {
637 my $list1_id = shift;
638 my $list2_id = shift;
640 my $list1 = $self->get_list($c, $list1_id);
641 my $list2 = $self->get_list($c, $list2_id);
643 my $combined_list_id = $self->new_list(
645 $list1->{name
}."_".$list2->{name
},
646 $list1->{description
}.", ".$list2->{description
});
648 my @combined_elements = (@
{$list1->{elements
}}, @
{$list2->{elements
}});
650 my @unique_elements = uniq
(@combined_elements);
652 foreach my $item (@unique_elements) {
653 $self->add_item($c, $combined_list_id, $item);
657 sub intersect_lists
: Path
('/list/intersect') Args
(2) {
660 my $list1_id = shift;
661 my $list2_id = shift;
663 my $list1 = $self->get_list($c, $list1_id);
664 my $list2 = $self->get_list($c, $list2_id);
666 my $combined_list_id = $self->new_list(
668 $list1->{name
}."_".$list2->{name
}."_intersect",
669 $list1->{description
}.", ".$list2->{description
});
671 my @intersect_elements = ();
673 my $list1_hashref; my $list2_hashref;
674 map { $list1_hashref->{$_}=1 } @
{$list1->{elements
}};
675 map { $list2_hashref->{$_}=1 } @
{$list2->{elements
}};
677 foreach my $item (keys(%{$list1_hashref})) {
678 if (exists($list1_hashref->{$item}) && exists($list2_hashref->{$item})) {
679 push @intersect_elements, $item;
683 my @unique_elements = uniq
(@intersect_elements);
685 foreach my $item (@unique_elements) {
686 $self->add_item($c, $combined_list_id, $item);
691 sub remove_element_action
:Path
('/list/item/remove') Args
(0) {
695 my $list_id = $c->req->param("list_id");
696 my $item_id = $c->req->param("item_id");
698 my $error = $self->check_user($c, $list_id);
701 $c->stash->{rest
} = { error
=> $error };
705 my $response = $self->remove_element($c, $list_id, $item_id);
707 $c->stash->{rest
} = $response;
711 sub update_element_action
:Path
('/list/item/update') Args
(0) {
715 my $list_id = $c->req->param("list_id");
716 my $item_id = $c->req->param("item_id");
717 my $content = $c->req->param("content");
718 my $error = $self->check_user($c, $list_id);
721 print STDERR
"update ".$list_id." ".$item_id." ".$content."\n";
724 $c->stash->{rest
} = { error
=> $error };
728 my $list = CXGN
::List
->new( { dbh
=> $c->dbc()->dbh(), list_id
=> $list_id });
729 $error = $list->update_element_by_id($item_id, $content);
733 $c->stash->{rest
} = { error
=> "An error occurred while attempting to update item $item_id" };
736 $c->stash->{rest
} = { success
=> 1 };
740 sub new_list
: Private
{
743 my ($name, $desc, $owner) = @_;
745 my $user_id = $self->get_user($c);
747 my $new_list_id = CXGN
::List
::create_list
($c->dbc->dbh(), $name, $desc, $owner);
753 sub get_list
: Private
{
758 my $list = $self->retrieve_list($c, $list_id);
760 my ($name, $desc, $type_id, $list_type) = $self->get_list_metadata($c, $list_id);
762 $c->stash->{rest
} = {
764 description
=> $desc,
766 type_name
=> $list_type,
771 sub retrieve_list
: Private
{
776 my $list = CXGN
::List
->new( { dbh
=> $c->dbc->dbh, list_id
=>$list_id });
777 my $public = $list->check_if_public();
779 my $error = $self->check_user($c, $list_id);
781 $c->stash->{rest
} = { error
=> $error };
785 my $list_elements_with_ids = $list->retrieve_elements_with_ids($list_id);
787 #print STDERR "LIST ELEMENTS WITH IDS: ".Dumper($list_elements_with_ids);
788 return $list_elements_with_ids;
792 sub remove_element
: Private
{
799 my $list = CXGN
::List
->new( { dbh
=> $c->dbc()->dbh(), list_id
=> $list_id });
800 my $error = $list->remove_element_by_id($item_id);
803 return { error
=> "An error occurred while attempting to delete item $item_id" };
806 return { success
=> 1 };
811 sub exists_item
: Private
{
817 my $list = CXGN
::List
->new( { dbh
=> $c->dbc()->dbh(), list_id
=> $list_id });
818 my $list_item_id = $list->exists_element($item);
819 return $list_item_id;
822 sub get_list_owner
: Private
{
827 my $list = CXGN
::List
->new( { dbh
=> $c->dbc()->dbh(), list_id
=> $list_id });
828 my $owner = $list->owner();
833 sub get_user
: Private
{
837 my $user = $c->user();
840 my $user_object = $c->user->get_object();
841 return $user_object->get_sp_person_id();
846 sub check_user
: Private
{
851 my $user_id = $self->get_user($c);
856 $error = "You must be logged in to manipulate this list.";
859 elsif ($self->get_list_owner($c, $list_id) != $user_id) {
860 $error = "You have insufficient privileges to manipulate this list.";
865 sub desynonymize_list
: Path
('/list/desynonymize') Args
(0) {
869 my $list_id = $c->req->param("list_id");
871 my $user_id = $self->get_user($c);
873 $c->stash->{rest
} = { error
=> 'You must be logged in to use lists.', };
876 my $schema = $c->dbic_schema("Bio::Chado::Schema");
877 my $dbh = $schema->storage->dbh;
879 my $list = CXGN
::List
->new( { dbh
=> $dbh, list_id
=> $list_id } );
880 my $flat_list = $list->retrieve_elements_with_ids($list_id);
881 my @name_list = map {@
{$_}[1]} @
{$flat_list};
882 my $dsyner = CXGN
::List
::Desynonymize
->new();
883 my $results = $dsyner
884 ->desynonymize($schema,$list->type(),\
@name_list);
885 $results->{'previous_list'} = \
@name_list;
886 $results->{'list_type'} = $list->type();
888 $c->stash->{rest
} = $results;