Merge pull request #4106 from solgenomics/topic/wishlist
[sgn.git] / mason / stock / index.mas
blobc60a3e0e63ad6d61a93b0c2191636ec7122411a7
1 <%doc>
3 =head1 NAME
5 /stock/index.mas - a page for displaying stock details (e.g. accession, population, etc.)
7 =head1 DESCRIPTION
9 parameters:
11 =over 1
13 =item $stockref
15 a hashref with all the parameters needed for printing the stock page!
17  $stockref->{stock_id}
18  $stockref->{stock}
19  $stockref->{schema}
20  $stockref->{uniquename}
21  $stockref->{curator}  (boolean)
22  $stockref->{submitter} (boolean)
23  $stockref->{is_owner} (boolean)
24  $stockref->{props} (hash of arrayrefs of stockprops. Keys = prop name, value = prop value)
25  $stockref->{has_pedigree} (boolean)
26  $stockref->{has_descendants} (boolean)
27  locus_add_uri
28  locus_autocomplete_uri => '/ajax/locus/autocomplete/'
29  cvterm_add_uri
30  cvterm_autocomplete_uri => '/ajax/cvterm/autocomplete/'
31  barcode_tempdir
32  barcode_tempuri
33  organism_autocomplete_uri => '/ajax/organism/autocomplete/'
35 =back
37 =head1 AUTHOR
39 Naama Menda <nm249@cornell.edu>
41 =cut
43 </%doc>
45 <%args>
46 $stock_row
47 $stockref => undef
48 $locus_add_uri => ''
49 $locus_autocomplete_uri => undef
50 $cvterm_add_uri => ''
51 $cvterm_autocomplete_uri => undef
52 $barcode_tempdir => undef
53 $barcode_tempuri => undef
54 $identifier_prefix => 'SGN'
55 $organism_autocomplete_uri => '/ajax/organism/autocomplete/'
56 </%args>
59 <%perl>
61 use Bio::Chado::Schema;
62 use CXGN::Chado::Stock;
63 use CXGN::Page::FormattingHelpers qw / html_optional_show info_table_html /;
64 use CXGN::People::Person;
65 use CXGN::Chado::Publication;
66 use CXGN::Cview::Map::SGN::Genotype;
67 use CXGN::Cview::MapOverviews;
69 my $stock = $stockref->{stock};
70 my $stock_id = $stockref->{stock_id};
71 my $action = $stockref->{action} || 'view';
72 my $person_id = $stockref->{person_id};
73 my $curator = $stockref->{curator};
74 my $submitter = $stockref->{submitter};
75 my $sequencer = $stockref->{sequencer};
76 my $pubs = $stockref->{pubs};
77 my $has_pedigree = $stockref->{has_pedigree};
78 my $has_descendants = $stockref->{has_descendants};
79 my $trait_ontology_db_name = $stockref->{trait_ontology_db_name};
80 my $editable_stock_props_string = $stockref->{editable_stock_props};
81 my $schema = $stockref->{schema};
82 my $dbh = $stockref->{dbh};
84 my @editable_stock_props = split "," , $editable_stock_props_string;
87 my ($type_name, $uniquename);
88 my $type = $stock_row ? $stock_row->type : undef;
89 $type_name  = $type->name() if $type;
90 $uniquename = $stock->get_uniquename if $type;
91 #################
92 my $is_owner = $stockref->{is_owner};
94 my $this_page = "/stock/$stock_id/view";
96 my $image_ids =  $stockref->{image_ids} || [] ;
97 my $related_image_ids =  $stockref->{related_image_ids} || [] ;
98 my $stockprops = $stockref->{props};
101 #my $pedigree= ['pedigree', 'male parent', 'female parent'];
102 # get pedigree of stock
103 #my $stock_pedigree = $stockref->{stock_pedigree};
104 #my $stock_descendants = $stockref->{stock_descendants};
106 my $allele_div = "stock_alleles";
107 my $new_locus_link = !$person_id ? qq|<a href="/user/login">[log-in to associate new locus]</a> | : '' ;
109 #owner
110 my $owners = $stockref->{editor_info};
111 my $owner_ids = $stockref->{owners};
112 my $owners_html = '';
113 my %unique_owners;
114 foreach my $o_id (@$owner_ids) {
115     $unique_owners{$o_id}++;
117 my @owner_ids = keys %unique_owners;
118 foreach my $o_id (@owner_ids){
119   my $person = CXGN::People::Person->new($dbh, $o_id);
120   my $first_name = $person->get_first_name;
121   my $last_name = $person->get_last_name;
122   $owners_html .= qq|<a href="/solpeople/personal-info.pl?sp_person_id=$o_id">$first_name $last_name</a> |;
124 my $editor_link_table = "<table class='table table-bordered'><thead><tr><th>Editor</th><th>Timestamp</th><th>Modification Note</th></tr></thead><tbody>";
125 foreach my $o_id (@$owners) {
126   my $person = CXGN::People::Person->new($dbh, $o_id->[0]);
127   my $first_name = $person->get_first_name;
128   my $last_name = $person->get_last_name;
129   $editor_link_table .= qq|<tr><td><a href="/solpeople/personal-info.pl?sp_person_id=$o_id->[0]">$first_name $last_name</a></td><td>$o_id->[1]</td><td>$o_id->[2]</td></tr>|;
131 $editor_link_table .= "</tbody></table>";
132 $editor_link_table = "<br/>".$owners_html."<br/><br/>".$editor_link_table;
134 #phenotypes measured directly on this stock
135 my $direct_phenotypes = $stockref->{direct_phenotypes} || undef;
137 # get all phenotypes of subjects
138 my $members_phenotypes = $stockref->{members_phenotypes};
139 my $p_download_link = '<a class="btn btn-sm btn-default" style="margin:3px" target="_blank" href = "/breeders/trials/phenotype/download?format=csv&timestamp=1&dataLevel=all&'.$type_name.'_list=['.$stock_id.']&search_type=complete&">Download All Phenotypes</a>';
141 ############################
142 my $map_html = $stockref->{map_html};
143 my $map;
144 if ($stock_id) {
145   $map = CXGN::Cview::Map::SGN::Genotype->new($dbh, $stock_id);
146   if ($map->get_chromosome_count > 1 ) {
147     my $overview = CXGN::Cview::MapOverviews::Generic->new($map,
148                                                            {
149                                                             dbh=> $dbh,
150                                                             basepath => $stockref->{cview_basepath},
151                                                             tempfiles_subdir => $stockref->{cview_tmp_dir } });
152     if ($overview) {
153       $overview->render_map();
154       $map_html .= $overview->get_image_html();
155     }
156   }
158 #########################################
159 my $has_qtl_data = $stockref->{has_qtl_data};
162 my $new_pub_link = $curator || $submitter || $sequencer  ?   qq|<a class="btn btn-sm btn-default" style="margin:3px" href="/chado/add_publication.pl?type=stock&amp;type_id=$stock_id&amp;refering_page=$this_page&amp;action=new">Associate publication</a>| : qq|<span class=\"btn btn-sm btn-default ghosted\" style="margin:3px" disabled>Associate publication</span>| ;
164 ## EUSOL, tgrc (stock_dbxref)
165 my $dbxrefs = $stockref->{dbxrefs};
166 my %source_dbs;
167 foreach my $db_name ( keys %$dbxrefs ) {
168   foreach my $dbxref ( @{ $dbxrefs->{$db_name} } ) {
169     my $url = $dbxref->db->urlprefix . $dbxref->db->url;
170     $url .= $dbxref->accession if $url =~ m/\?$|\=$/ ;
171     $source_dbs{$url} = $db_name . ": " . $dbxref->accession if $url;
172   }
175 my $ontology_subtitle = $curator || $submitter || $sequencer  ?
176   qq|<a class="btn btn-sm btn-default" style="margin:3px" href="javascript:Tools.toggleContent('associate_cvterm_form', 'stock_ontology')">Add ontology annotations</a> | :
177   qq |<span class = "btn btn-default btn-sm ghosted" style="margin:3px" disabled>Add ontology annotations</span> |;
179 my $add_phenotype_link =  $curator || $submitter || $sequencer  ? qq| <a href="javascript:Tools.toggleContent('add_phenotype_form', 'stock_phenotype')" >[Add phenotype]</a> | :   qq |<span class = "ghosted"> [Add phenotype]</span> |;
181 my $edit_privs = $curator || $submitter || $sequencer;
183 my $jbrowse_path = $c->config->{jbrowse_path};
184 my @path_parts = split('/', $jbrowse_path);
185 my $basepath = $path_parts[1];
186 my $test_url = "/" . $basepath . "/jbrowse.conf";
187 my $jbrowse_url = $jbrowse_path . "%2Faccessions%2F" . $stock_id . "&tracks=DNA%2CGene%20exons%2C" . $uniquename . "_2015_V6_imputed&highlight=";
190 my $released_variety_link = '<button class="btn btn-default btn-sm" style="margin:3px" id="released_variety_link" disabled>Add released variety name</button>';
192 if ($person_id && ($submitter || $curator || $sequencer)) { $released_variety_link = qq | <button class="btn btn-default btn-sm" style="margin:3px" id="released_variety_link" >Add released variety name</button> |; }
194 </%perl>
196 <& /util/import_css.mas, paths => ['/documents/inc/datatables/jquery.dataTables.css'] &>
198 <& /util/import_javascript.mas,
199    classes => ["jquery", "jqueryui", "thickbox", "CXGN.Page.FormattingHelpers", "jquery.cookie", "CXGN.Stock", "d3.d3v4Min" ],
200   entries => ["sequenced_accessions"]
203 <script language="javascript">
204 function jqueryStuff() {
205    jQuery(function() {
206      jQuery("#species_name").autocomplete({
207         source: '/organism/autocomplete'
208      });
209   });
211 </script>
214 <& /page/page_title.mas, title=> join( ': ', grep $_, ucfirst($type_name), $uniquename ) || 'Create a new stock' &>
217 <&| /page/info_section.mas, title=>"Stock details" , collapsible=>1, collapsed=>0, subtitle => "<button class='btn btn-sm btn-default' style='margin:3px' name='stock_new_qtl_link'>New QTL population</button> <button class='btn btn-sm btn-default' style='margin:3px' name='stock_go_to_stock_search'>Back to stock search</button>"  &>
219     <div class="panel panel-default">
220         <div class="panel-body">
222             <div class="row">
223                 <div class="col-sm-6">
225                     <& /page/form.mas,
226                         object_type=>'stock',
227                         object_id=>"$stock_id",
228                         form_name=> 'stock_form',
229                         server_side_script => '/phenome/stock/stock_ajax_form.pl',
230                         form_div_name=>'stock_details',
231                         js_object_name=> 'stockForm',
232                         page_url => "/stock/$stock_id/view/" ,
233                         #alternate_new_button => '<a class="btn btn-sm btn-default" href ="/stock/0/new">New</a>'
234                         alternate_new_button => '',,
235                         alternate_ghosted_new_button => '',
236                         alternate_delete_button => '',
237                         alternate_ghosted_delete_button => ''
238                     &>
240                      
241                 </div>
242                 <div class="col-sm-6">
243                     <br /><br />
244                     <& /util/barcode.mas, identifier => "$identifier_prefix"."$stock_id", text=> "$identifier_prefix stock $stock_id ($uniquename)", format=>"stock_qrcode"  &>
245                     <br /><br />
246                 </div>
247             </div>
249             <div class="row">
250               <div class="col-sm-6">
251                 <&| /page/info_section.mas, title => "Released variety name", subtitle=>$released_variety_link, is_subsection => 1 &>
252                   <& /stock/stockprops.mas,
253                      stock_id  =>$stock_id,
254                     form_div_id => 'released_variety_link', 
255                     props      => ['released_variety_name'],
256                     div_name   => 'released_variety_name',
257                     edit_privs => $edit_privs,
258                     subset     => ['released_variety_name'],
259                     editable   => ['released_variety_name']  &>
260                  </&>  
261               </div>
262               </div>
263               <div class="row">
264                 <div class="col-sm-6">
265                 </div>
266               </div>
267           </div>
268        </div>
269 </&>
272                       
274 <&| /page/info_section.mas, title => "Navigator" , collapsible=> 1, collapsed=>0 &>
276 % my $subtitle = $edit_privs ? "<button class=\"btn btn-sm btn-primary\" style=\"margin:3px\" id=\"stock_add_synonym\" >Add Synonym</button>" : "<button disabled class=\"btn btn-sm btn-primary\" style=\"margin:3px\" title=\"Login to add info\">Add Synonym</button>";
277 % my $props_subtitle = $edit_privs ? "<button class=\"btn btn-sm btn-primary\" style=\"margin:3px\" id=\"stock_add_props\" >Add Additional Info</button>" : "<button disabled class=\"btn btn-sm btn-primary\" style=\"margin:3px\" title=\"Login to add info\">Add Additional Info</button>";
279     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, type_name => $type_name, stockref => $stockref, buttons_html => $subtitle.$props_subtitle, info_section_title => "<h4 style='display:inline'>Additional Info</h4>", info_section_subtitle => 'View and edit additional properties such as synonyms, editors, and all types of properties.', icon_class => "glyphicon glyphicon-info-sign", info_section_id => "stock_additional_info_section", stockprops => $stockprops, edit_privs => $edit_privs, editable_stock_props => \@editable_stock_props, editor_link => $editor_link_table, source_dbs => \%source_dbs, locus_add_uri => $locus_add_uri, new_locus_link => $new_locus_link, allele_div => $allele_div, is_owner => $is_owner &>
281 % if ($type_name eq 'accession' || $type_name eq 'plant' || $type_name eq 'plot' || $type_name eq 'subplot' || $type_name eq 'tissue_sample'){
282     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Experiment Usage</h4>", info_section_subtitle => 'View experiments that this stock has been used in.', icon_class => "glyphicon glyphicon-leaf", info_section_id => "stock_trials_section" &>
283 % }
285 % if ($type_name eq 'accession' || $type_name eq 'plant' || $type_name eq 'plot' || $type_name eq 'subplot' || $type_name eq 'tissue_sample'){
287 %    my $trait_assayed_buttons = $type_name eq 'plot' ? "<button class='btn btn-sm btn-primary' style='margin:3px' id='stock_download_phenotypes_button'>Download Phenotypes</button> $p_download_link <a class='btn btn-sm btn-default' style='margin:3px' target='_blank' href = '/breeders/plot_phenotyping?stock_id=$stock_id'>Direct plot phenotyping</a>" : "<button class='btn btn-sm btn-primary' style='margin:3px' id='stock_download_phenotypes_button'>Download Phenotypes</button> $p_download_link";
289     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Traits Assayed</h4>", info_section_subtitle => 'View and download phenotypic data for this stock.', icon_class => "glyphicon glyphicon-equalizer", info_section_id => "stock_traits_section", buttons_html => $trait_assayed_buttons &>
290 % }
292 % if ($type_name eq 'accession' || $type_name eq 'plant' || $type_name eq 'plot' || $type_name eq 'tissue_sample'){
294 %   my $sequencing_status_button = '';
295 %   if ($c->user) {
296 %       $sequencing_status_button = '<button id="show_sequencing_info_dialog_button" class="btn btn-primary btn-sm" data-toggle="modal" style="margin:3px" data-target="#edit_sequencing_info_dialog">Add sequencing info</button>';
297 %   }
298 %   else {
299 %       $sequencing_status_button = '<button disabled id="show_sequencing_info_dialog_button" class="btn btn-primary btn-sm" data-toggle="modal" style="margin:3px" data-target="#edit_sequencing_info_dialog">Add sequencing info</button>';
300 %   }
302       <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Sequencing Status</h4>", info_section_subtitle => 'View and edit sequencing status info for this stock.', icon_class => "glyphicon glyphicon-inbox", info_section_id => "stock_sequencing_status_section", buttons_html => "$sequencing_status_button", map_html => $map_html &>
303         
304         <!-- buttons_html => '<a class="btn btn-default btn-sm" style="margin:3px" href = "/stock/'.$stock_id.'/genotypes">Download All Genotypes</a>', -->
305         
306     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Genotype Marker Data</h4>", info_section_subtitle => 'View and download phenotypic data for this stock.', icon_class => "glyphicon glyphicon-map-marker", info_section_id => "stock_genotypes_section",  map_html => $map_html &>
307 % }
309 % if ($type_name eq 'accession'){
311 <%perl>
312         my $collapsible = 0;
313         if ($has_pedigree==1) {
314             $collapsible = 1;
315         }
316         my $add_parent_link = '<button class="btn btn-primary btn-sm" style="margin:3px" id="add_parent_link" disabled>Add parent</button>';
317         if ($person_id && ($submitter || $curator || $sequencer)) { $add_parent_link = qq | <button class="btn btn-primary btn-sm" style="margin:3px" id="add_parent_link" >Add parent</button> |; }
319         my $remove_parent_link = '<button class="btn btn-default btn-sm" style="margin:3px" id="remove_parent_link" disabled>Remove parent</button>';
320         if ($person_id && ($submitter || $curator || $sequencer)) { $remove_parent_link = qq | <button class="btn btn-default btn-sm" style="margin:3px" id="remove_parent_link">Remove parent</button> |; }
321 </%perl>
323     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Pedigree</h4>", info_section_subtitle => 'View and edit pedigree information.', icon_class => "glyphicon glyphicon-random", info_section_id => "stock_pedigree_section", buttons_html => $add_parent_link.$remove_parent_link, has_pedigree => $has_pedigree, info_section_collapsed => 0 &>
324 % }
326     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Related Stocks</h4>", info_section_subtitle => 'View any plots, plants, tissue_sample, and/or accessions that are linked to this stock.', icon_class => "glyphicon glyphicon-retweet", info_section_id => "stock_related_stock_section", stock_uniquename => $uniquename, type_name => $type_name &>
328     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Images</h4>", info_section_subtitle => 'View and add images of this stock and of related stocks.', icon_class => "glyphicon glyphicon-camera", info_section_id => "stock_images_section", image_ids => $image_ids, related_image_ids => $related_image_ids, dbh => $dbh, buttons_html => qq|<a class="btn btn-sm btn-default" style="margin:3px" href="/image/add?type_id=$stock_id&action=new&type=stock&refering_page=$this_page">Add new image</a><a class="btn btn-sm btn-default" style="margin:3px" id="stock_images_section_compare_images_button">Compare Images</a>| &>
330     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Literature Annotation</h4>", info_section_subtitle => 'View annotations for this stock found in literatur and ontologies.', icon_class => "glyphicon glyphicon-book", info_section_id => "stock_literature_annotation_section", buttons_html => $new_pub_link.$ontology_subtitle, pubs => $pubs, cvterm_add_uri => $cvterm_add_uri, stockref => $stockref, trait_ontology_db_name => $trait_ontology_db_name, is_owner => $is_owner, dbh=>$dbh &>
332     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>JBrowse Genome Alignments</h4>", info_section_subtitle => 'View JBrowse tracks for this stock.', icon_class => "glyphicon glyphicon-align-left", info_section_id => "stock_jbrowse_section" &>
334     <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Comments</h4>", info_section_subtitle => 'View and add comments to this stock.', icon_class => "glyphicon glyphicon-pencil", info_section_id => "stock_comments_section", referer => $this_page &>
336       <& /page/detail_page_2_col_section.mas, stock_id => $stock_id, info_section_title => "<h4 style='display:inline'>Obsolete This Stock</h4>", info_section_subtitle => 'Make a stock obsolete so that it does not show in searches.', icon_class => "glyphicon glyphicon-trash", info_section_id => "stock_delete_section" &>
338 </&>
340 <& /stock/download_stock_phenotypes_dialog.mas, stock_id => $stock_id, stock_name => $uniquename, stock_type => $type_name &>
342 <div id="remove_parent_dialog">
343     Remove a parent (this will only remove the link to the parent, not the parent accession itself).
344     <br /><br />
345     <div id="remove_parent_list">[loading parent list...]</div>
346 </div>
349 <&| /page/info_section.mas, title=>"Phenotype data " ,  subtitle=>$p_download_link ,  collapsible => 1, collapsed => 1 &>
350 % foreach my $project (keys %$direct_phenotypes) {
351 %   my $rs = $direct_phenotypes->{$project} ;
353 <&| /page/info_section.mas,
354     id       => "stock_phenotype",
355     title    =>"Experiment: $project",
356     subtitle => $add_phenotype_link,
357     is_subsection => 1,
358     collapsible => 1
360     <& /stock/add_phenotype.mas,
361       stock_id => $stock_id ,
362       trait_ontology_db_name => $trait_ontology_db_name,
363       project=>$project
364     &>
365   <& /phenotypes/phenotype_data.mas ,
366       phenotypes=> $rs
367     &>
368   </&>
369 % }
371 % foreach my $key (keys %$members_phenotypes) {
372 % my $m_rs = $members_phenotypes->{$key};
373 <&| /page/info_section.mas,
374      title         => "Member phenotypes",
375      subtitle      => $key,
376      is_subsection => 1,
377      collapsible   => 1,
378  &>
379     <& /phenotypes/phenotype_data.mas,
380          phenotypes => $m_rs,
381          object_id  => $stock_id,
382          has_qtl    => $has_qtl_data,
383      &>
384   </&>
385 % }
386 </&>
388 <div id="stock_trials_info_popup">
389     <table id="stock_trials_info_table" >
390         <thead>
391             <tr><th>Trait</th><th>Average</th><th>Std dev</th><th>Count</th></tr>
392         </thead>
393     </table>
394 </div>
396 <script>
397     jQuery(document).ready(function() {
398         stock_detail_page_init_dialogs();
400         jQuery('[name="stock_new_qtl_link"]').click(function(){
401             window.location.href = '/phenome/qtl_form.pl';
402         });
404         jQuery('[name="stock_go_to_stock_search"]').click(function(){
405             window.location.href = '/search/stocks/';
406         });
408         jQuery('#remove_parent_link').click( function() {
409             jQuery('#remove_parent_dialog').dialog("open");
410             get_remove_parents_list(<% $stock_id %>);
411         });
413         jQuery.ajax({
414             url: "<% $test_url %>",
415             success: function(response) {
416                 if ( response.indexOf("Accession_<%$stock_id%>") > -1 ) {  // if dataset is found, create and display link
417                     jQuery('#jbrowse_check').replaceWith('<a id="jbrowse_link" href="<% $jbrowse_url %>">View the tracks for this accession in JBrowse</a>');
418                 }
419                 else { // if not found, display message that dataset doesn't exist
420                     jQuery('#jbrowse_check').html(" <i>This accession does not have any data in Jbrowse.</i>");
421                 }
422             },
423             error: function() {
424                 jQuery('#jbrowse_check').html(" <i>Jbrowse has not been set up for this database.</i>");
425             }
426         });
427   });
428 </script>