1 ######################################################################
3 # Displays an editable allele detail page.
5 ######################################################################
7 my $allele_detail_page = CXGN
::Phenome
::AlleleDetailPage
->new();
9 package CXGN
::Phenome
::AlleleDetailPage
;
11 use base qw
/CXGN::Page::Form::SimpleFormPage/;
16 use CXGN
::Page
::FormattingHelpers
qw(info_section_html
23 use CXGN
::Phenome
::Locus
;
24 use CXGN
::Phenome
::Allele
;
25 use CXGN
::Phenome
::AlleleSynonym
;
26 use CXGN
::Chado
::Publication
;
27 use CXGN
::People
::PageComment
;
30 use CatalystX
::GlobalContext
qw( $c );
34 my $schema = 'phenome';
35 my $self = $class->SUPER::new(@_);
41 $self->set_dbh( CXGN::DB::Connection->new('phenome') );
42 my %args = $self->get_args();
43 my $allele_id = $args{allele_id};
44 unless ( !$allele_id || $allele_id =~ m /^\d+$/ ) {
45 $self->get_page->message_page(
46 "No allele exists for identifier $allele_id");
48 $self->set_object_id($allele_id);
50 CXGN::Phenome::Allele->new( $self->get_dbh, $self->get_object_id ) );
52 $self->set_primary_key("allele_id");
53 $self->set_owners( $self->get_object()->get_owners() )
54 ; #instead of get_sp_person_id()
57 # override store to check if an allele with the submitted symbol already exists for this locus
61 my $allele = $self->get_object();
62 my $allele_id = $self->get_object_id();
63 $allele->set_is_default('f');
64 my %args = $self->get_args();
65 my $action = $args{action};
66 my $locus_id = $args{locus_id};
69 $allele->exists_in_database( $args{allele_symbol}, $args{locus_id} );
71 $self->get_page()->message_page($message);
75 $self->send_allele_email();
76 $self->SUPER::store(1);
79 $allele_id = $allele->get_allele_id();
81 ->client_redirect("/phenome/allele.pl?allele_id=$allele_id");
87 my %args = $self->get_args();
88 $self->check_modify_privileges();
93 my $allele_symbol = $self->get_object()->get_allele_symbol();
94 my $locus_id = $self->get_object()->get_locus_id();
96 $locus = CXGN::Phenome::Locus->new( $self->get_dbh(), $locus_id );
97 $locus_name = $locus->get_locus_name();
98 $locus->remove_allele( $args{allele_id} );
99 $self->send_allele_email('delete');
102 $self->get_page()->header();
106 qq { Removed allele "$allele_symbol" association from locus "$locus_name". };
108 qq { <a href="/locus/$locus_id/view">back to locus</a> };
111 $self->get_page()->footer();
123 # $self->delete_dialog("Delete", "Object",
124 # $self->get_primary_key(),
126 # "<a href=\"".$self->get_script_name()."?".$self->get_primary_key()."=".$id."&action=view\">Go back to detail page without deleting</a>");
134 $self->check_modify_privileges();
135 my %args = $self->get_args();
137 my $object_name = shift;
138 my $field_name = shift;
139 my $object_id = shift;
143 . $self->get_script_name() . "?"
144 . $self->get_primary_key() . "="
146 . "&action=view\">Go back to allele page without deleting</a>";
148 $self->get_page()->header();
150 page_title_html("$title");
153 Delete allele (id=$object_id)?
154 <input type="hidden" name="action" value="delete" />
155 <input type="hidden" name="$field_name" value="$object_id" />
157 <input type="submit" value="Delete" />
164 $self->get_page()->footer();
169 my %args = $self->get_args();
171 my $allele = $self->get_object();
172 my $allele_id = $self->get_object_id();
173 my $allele_symbol = $allele->get_allele_symbol();
174 my $locus_id = $allele->get_locus_id();
175 my $locus_name = $allele->get_locus_name();
177 my $stock_ids = $allele->get_stock_ids();
178 my $default_allele = $allele->get_is_default();
180 ###import js libraries
181 $self->get_page->jsan_use("CXGN.Phenome.Tools");
182 $self->get_page->jsan_use("CXGN.Phenome.Locus");
183 $self->get_page->jsan_use("MochiKit.DOM");
184 $self->get_page->jsan_use("Prototype");
185 $self->get_page->jsan_use("jquery");
186 $self->get_page->jsan_use("thickbox");
189 my $page = "../phenome/allele.pl?allele_id=$allele_id";
190 my $action = $args{action} || "";
191 if ( $default_allele eq 't'
192 || ( !$allele_id & ( $action eq 'view' || $action eq 'edit' ) ) )
194 $self->get_page->message_page("No allele exists for this identifier");
197 if ( $args{locus_id} ) {
198 $locus_id = $args{locus_id};
200 CXGN::Phenome::Locus->new( $self->get_dbh(), $locus_id )
203 $self->get_page->header("SGN allele $allele_symbol of locus $locus_name");
204 print page_title_html("Allele:\t'$allele_symbol'\n");
206 my $edit_links = $self->get_edit_links();
209 $edit_links . "<br />" . $self->get_form()->as_table_string() . "<br />";
211 my $allele_synonym_link =
212 "allele_synonym.pl?allele_id=$allele_id&action=new";
213 my $allele_synonyms = "";
214 foreach my $a_synonym ( $allele->get_allele_aliases() ) {
215 $allele_synonyms .= $a_synonym->get_allele_alias() . " ";
218 $allele_html .= qq|<br><b> Allele synonyms: </b>$allele_synonyms|;
219 unless ( $self->get_action =~ /new/ ) {
221 qq|<a href="$allele_synonym_link"> [Add/remove] </a> <br><br>|;
225 my $login_user = $self->get_user();
226 my $login_user_id = $login_user->get_sp_person_id();
227 my $login_user_type = $login_user->get_user_type();
228 my $object_owner = $allele->get_sp_person_id();
229 my @locus_owners = $allele->get_locus()->get_owners();
230 if ( $login_user_type eq 'curator'
231 || $login_user_id == $object_owner
232 || ( grep { /^$login_user_id$/ } @locus_owners ) )
234 my $history_data = $self->print_allele_history() || "";
235 $allele_html .= $history_data;
237 print info_section_html(
238 title => 'Allele details',
239 contents => $allele_html,
241 my $stocks_html = "<TABLE>";
243 ; # hash of image arrays. Keys are stock_ids, values are arrays of image_ids
248 my $schema = $c->dbic_schema('Bio::Chado::Schema' , 'sgn_chado');
249 foreach my $stock_id (@$stock_ids) {
250 my $stock = CXGN::Chado::Stock->new( $schema, $stock_id );
251 my $stock_name = $stock->get_name();
252 $stockHash{$stock_id} = $stock_name;
254 my @images = map SGN::Image->new( $self->get_dbh, $_->[0], $c ), $stock->get_image_ids();
255 foreach my $image (@images) {
256 my $image_id = $image->get_image_id();
257 my $img_src_tag = $image->get_img_src_tag("thumbnail");
258 $imageHash{$image_id} = $img_src_tag;
259 push @{ $imageHoA{$stock_id} }, $image_id;
262 #if there are no associated images with this stock:
263 if ( !@images ) { push @no_image, $stock_id; }
266 sort { @{ $imageHoA{$b} } <=> @{ $imageHoA{$a} } }
270 my $stock_name = $stockHash{$stock_id};
272 qq|<TR valign="top"><TD><a href="/stock/$stock_id/view">$stock_name </a></TD>|;
274 foreach my $image_id ( @{ $imageHoA{$stock_id} } ) {
275 my $image_src_tag = $imageHash{$image_id};
277 qq |<TD><a href="../image/index.pl?image_id=$image_id">$image_src_tag</a></TD>|;
279 $stocks_html .= "</TR>";
281 if ( !@$stock_ids ) { $stocks_html = undef; }
282 else { $stocks_html .= "</TABLE>"; }
284 foreach my $stock_id (@no_image) {
285 my $stock_name = $stockHash{$stock_id};
287 qq|<a href="/stock/$stock_id/view">$stock_name </a>|;
290 my $stock_subtitle = "";
293 && ( $login_user_type eq 'curator'
294 || $login_user_type eq 'submitter'
295 || $login_user_type eq 'sequencer' )
300 qq| <a href="javascript:Tools.toggleContent('associateStockForm', 'allele_accessions')">[Associate accession]</a> |;
302 $stocks_html .= $self->associate_stock;
306 qq|<span class= "ghosted">[Associate accession]</span> |;
309 print info_section_html(
310 title => 'Associated accessions',
311 subtitle => $stock_subtitle,
312 contents => $stocks_html,
313 id => "allele_accessions",
320 my ( $pubmed_links, $pub_count, $genbank, $gb_count ) =
321 $self->get_dbxref_info();
324 qq|<a href="/chado/add_feature.pl?type=allele&type_id=$allele_id&&refering_page=$page&action=new">[Associate new genbank sequence]</a>|
327 print info_section_html(
328 title => "Sequence annotations ($gb_count)",
330 contents => $genbank,
335 qq|<a href="../chado/add_publication.pl?type=allele&type_id=$allele_id&&refering_page=$page&action=new">[associate new publication]</a>|
338 print info_section_html(
339 title => 'Literature annotation',
340 subtitle => $new_pub_link,
341 contents => $pubmed_links,
345 ####add page comments
346 if ($allele_symbol) {
347 my $page_comment_obj =
348 CXGN::People::PageComment->new( $self->get_dbh(), "allele",
349 $allele_id, $self->get_page()->{request}->uri()."?".$self->get_page()->{request}->args() );
350 print $page_comment_obj->get_html();
353 $self->get_page()->footer();
359 my $allele = $self->get_object();
361 my %args = $self->get_args();
362 my $mode_names_ref = [ 'recessive', 'partially dominant', 'dominant' ];
363 my $locus_name = $allele->get_locus_name();
364 my $locus_id = $allele->get_locus_id();
365 if ( $self->get_action =~ /new/ ) {
366 $locus_id = $args{locus_id};
368 CXGN::Phenome::Locus->new( $self->get_dbh(), $locus_id );
369 $locus_name = $locus_obj->get_locus_name();
372 qq|<a href= "/locus/$locus_id/view">$locus_name</a>|;
374 $self->get_form()->add_label(
375 display_name => "Locus name",
376 field_name => "locus_name",
377 contents => $locus_name,
380 $self->get_form()->add_field(
381 display_name => "Allele symbol ",
382 field_name => "allele_symbol",
384 getter => "get_allele_symbol",
385 setter => "set_allele_symbol",
386 validate => 'allele_symbol',
388 $self->get_form()->add_field(
389 display_name => "Allele name ",
390 field_name => "allele_name",
392 getter => "get_allele_name",
393 setter => "set_allele_name",
394 validate => 'string',
397 $self->get_form()->add_select(
398 display_name => "Mode of inheritance ",
399 field_name => "mode_of_inheritance",
401 contents => $args{mode_of_inheritance},
402 getter => "get_mode_of_inheritance",
403 setter => "set_mode_of_inheritance",
404 select_list_ref => $mode_names_ref,
405 select_id_list_ref => $mode_names_ref,
408 $self->get_form()->add_textarea(
409 display_name => "Phenotype ",
410 field_name => "allele_phenotype",
412 getter => "get_allele_phenotype",
413 setter => "set_allele_phenotype",
418 $self->get_form()->add_textarea(
419 display_name => "Sequence/mutation ",
420 field_name => "allele_sequence",
422 getter => "get_sequence",
423 setter => "set_sequence",
428 $self->get_form()->add_hidden(
429 field_name => "allele_id",
430 contents => $args{allele_id},
432 getter => "get_allele_id",
433 setter => "set_allele_id"
436 $self->get_form()->add_hidden(
437 field_name => "action",
441 $self->get_form()->add_hidden(
442 field_name => "sp_person_id",
443 contents => $self->get_user()->get_sp_person_id(),
445 setter => "set_sp_person_id",
449 $self->get_form()->add_hidden(
450 field_name => "updated_by",
451 contents => $self->get_user()->get_sp_person_id(),
453 setter => "set_updated_by",
456 $self->get_form()->add_hidden(
457 field_name => "locus_id",
458 contents => $args{locus_id},
460 getter => "get_locus_id",
461 setter => "set_locus_id"
464 if ( $self->get_action =~ /view|edit/ ) {
466 $self->get_form->from_database();
468 elsif ( $self->get_action =~ /store/ ) {
469 $self->get_form->from_request( $self->get_args() );
474 #########################################################
476 sub get_dbxref_info {
478 my $allele = $self->get_object();
479 my %dbs = $allele->get_dbxref_lists()
480 ; #hash of arrays. keys=dbname values= dbxref objects
482 my ( $pubs, $genbank );
485 foreach ( @{ $dbs{'PMID'} } ) {
487 my ( $detail, $abstract ) =
488 CXGN::Chado::Publication::get_pub_info( $_->[0], 'PMID' )
490 $pubs .= "<div>" . $detail . html_optional_show(
491 "abstract$abs_count",
492 'Show/hide abstract',
494 0, #< do not show by default
495 'abstract_optional_show', #< don't use the default button-like style
498 foreach ( @{ $dbs{'SGN_ref'} } ) {
501 CXGN::Chado::Publication::get_pub_info( $_->[0], 'SGN_ref' )
503 $pubs .= "<div>" . $det . html_optional_show(
504 "abstract$abs_count",
505 'Show/hide abstract',
507 0, #< do not show by default
508 'abstract_optional_show', #< don't use the default button-like style
513 foreach ( @{ $dbs{'DB:GenBank_GI'} } ) {
514 if ( $_->[1] eq '0' ) {
516 my $url = $_->[0]->get_urlprefix() . $_->[0]->get_url();
518 $self->CXGN::Chado::Feature::get_feature_name_by_gi(
519 $_->[0]->get_accession() );
520 my $description = $_->[0]->get_description();
522 qq|<a href="$url$gb_accession" target="blank">$gb_accession</a> $description<br />|;
526 return ( $pubs, $abs_count, $genbank, $gb_count );
533 my $form_name = shift;
535 $self->get_new_link_html($form_name) . " "
536 . $self->get_edit_link_html($form_name) . " "
537 . $self->get_delete_link_html($form_name);
541 sub get_new_link_html {
543 my $form_name = shift;
545 my $script_name = $self->get_script_name();
546 my $primary_key = $self->get_primary_key();
547 my $object_id = $self->get_object_id();
548 my $locus_id = $self->get_object->get_locus_id();
551 qq { <a href="$script_name?action=new&locus_id=$locus_id&form=$form_name">[New]</a> };
552 if ( $self->get_action() eq "edit" ) {
553 $new_link = qq { <span class="ghosted">[New]</span> };
555 if ( $self->get_action() eq "new" ) {
556 $new_link = qq { <a onClick="history.go(-1)">[Cancel]</a> };
561 sub print_allele_history {
564 my $allele = $self->get_object();
568 my @history_objs = $allele->show_history(); #array of allele_history objects
570 foreach my $h (@history_objs) {
572 my $created_date = $h->get_create_date();
573 $created_date = substr $created_date, 0, 10;
575 my $history_id = $h->{allele_history_id};
576 my $updated_by_id = $h->{updated_by};
578 CXGN::People::Person->new( $self->get_dbh(), $updated_by_id );
579 my $u_first_name = $updated->get_first_name();
580 my $u_last_name = $updated->get_last_name();
582 qq |<a href="/solpeople/personal-info.pl?sp_person_id=$updated_by_id">$u_first_name $u_last_name</a> ($created_date)|;
587 $h->get_allele_symbol, $h->get_allele_name,
588 $h->get_allele_phenotype, $h->get_sequence,
596 $history_data .= columnar_table_html(
598 [ 'Symbol', 'Name', 'Phenotype', 'Sequence', 'Updated by', ],
604 $print_history = html_optional_show(
606 'Show allele history',
607 qq|<div class="minorbox">$history_data</div> |,
611 return $print_history;
612 } #print_allele_history
614 sub associate_stock {
616 my $allele_id = $self->get_object_id();
617 my $sp_person_id = $self->get_user->get_sp_person_id();
618 my $locus_id = $self->get_object()->get_locus_id();
620 my $associate_html = qq^
622 <div id="associateStockForm" style="display: none">
627 onkeyup="Locus.getStocks(this.value);">
629 id="associate_stock_button"
630 value="associate accession"
632 onclick="Locus.associateAllele('$sp_person_id', '$allele_id');this.disabled=true;">
633 <select id="stock_select"
635 onchange="Tools.enableButton('associate_stock_button');"
641 return $associate_html;
644 sub send_allele_email {
647 my $allele_id = $self->get_object()->get_allele_id();
648 my $allele_name = $self->get_object()->get_allele_name();
649 my %args = $self->get_args();
650 my $locus_id = $args{locus_id};
652 my $subject = "[New allele details stored] allele $allele_id";
654 $self->get_user()->get_first_name() . " "
655 . $self->get_user()->get_last_name();
656 my $sp_person_id = $self->get_user()->get_sp_person_id();
659 qq |http://solgenomics.net/locus/$locus_id/view|;
661 qq |http://solgenomics.net/solpeople/personal-info.pl?sp_person_id=$sp_person_id|;
662 my $usermail = $self->get_user()->get_private_email();
664 if ( $action eq 'delete' ) {
666 "$username ($user_link) has obsoletes allele $allele_id ($locus_link) \n$usermail";
670 "$username ($user_link) has submitted data for allele $allele_name ($locus_link) \n$usermail";
674 "$username ($user_link) has submitted a new allele $allele_name for locus $locus_link \n$usermail";
676 CXGN::Contact::send_email( $subject, $fdbk_body,
677 'sgn-db-curation@sgn.cornell.edu' );
678 CXGN::Feed::update_feed( $subject, $fdbk_body );