3 $odk_crossing_data_service_name => undef
4 $odk_crossing_data_service_url => undef
5 $odk_crossing_data_test_form_name => undef
6 $odk_phenotyping_data_service_name => undef
7 $odk_phenotyping_data_service_url => undef
10 <& /util/import_javascript.mas, classes => [ 'jstree.dist.jstree', 'd3.d3Min', 'SGN.Scatterplot' ] &>
12 <& /util/import_css.mas, paths => ['/static/documents/inc/jstree_theme/jstree-bstheme-min.css'] &>
15 <& /page/page_title.mas, title=>"Manage ODK Data Collection" &>
17 <div class="container-fluid">
21 <ul><li>ODK is an application that allows mobile data collection using user defined forms on Android or IOS devices. Data collected on the device can be instantaneously synched to the ODK server. To find out more go to the <a href="https://opendatakit.org/">ODK site</a>. Many services have developed web interfaces to better streamline the ODK experience. These services assist in creating forms, deploying forms to your mobile application, and visualizing data uploaded back from the mobile device. Currently we are working with <a href="http://www.smap.com.au">SMAP</a> and <a href="https://ona.io/home/">ONA</a> as two ODK services.</li></ul>
22 <h4>What do I do from this page?</h4>
24 <li>ONA is currently being used for collecting crossing information. This requires exporting a crossing plan from here to the ONA server. The crossing plan guides collection of cross information and this data is synched with ONA using ODK. From here, we run a script twice a day, which pulls data on ONA into our database.
26 <li>SMAP is currently being used for collecting phenotype information. The user collects phenotypes using a form they previously created. The questions in the form map directly to terms in the ontology. As they collect data on the mobile device, the data is synched to SMAP. From here, we run a script twice a day, which pulls data on SMAP into our database.
33 <& /breeders_toolbox/cross_wishlist.mas &>
34 <&| /page/info_section.mas, title=>'Crossing Data: ONA ODK Application', collapsible=>1, collapsed=>0, is_subsection=>1, subtitle=>'' &>
36 <div class="panel panel-default">
37 <div class="panel-body">
38 <form class="form-horizontal" id="import_odk_cross_data_form" name="import_odk_cross_data_form">
39 <div class="form-group">
40 <label class="col-sm-4 control-label">Select An ODK Form on ONA: </label>
41 <div class="col-sm-8" >
42 <div id="import_odk_cross_data_available_forms">LOADING...</div>
49 <&| /page/info_section.mas, title=>'Management', collapsible=>1, collapsed=>0, is_subsection=>1, subtitle=>'' &>
51 <div class="panel panel-default">
52 <div class="panel-body">
54 <div class="col-sm-1">
55 <span style="font-size:3em;" class="glyphicon glyphicon-transfer"></span>
57 <div class="col-sm-11">
58 <button class="pull-right btn btn-primary btn-sm" id="create_cross_wishlist" >Export Cross Wishlist (Crossing Plan) to Selected Form on ONA</button>
60 <button class="pull-right btn btn-info btn-sm" id="import_odk_cross_data" >Import Crossing Data from Selected Form on ONA</button>
67 <div class="panel panel-default">
68 <div class="panel-body">
70 <div class="col-sm-1">
71 <span style="font-size:3em;" class="glyphicon glyphicon-time"></span>
73 <div class="col-sm-11">
74 <form class="form-horizontal" id="schedule_import_odk_cross_data_form" name="schedule_import_odk_cross_data_form">
75 <div class="form-group">
76 <label class="col-sm-6 control-label">Schedule Import For Selected Form: </label>
77 <div class="col-sm-4" >
78 <select class="form-control" id="schedule_import_odk_crossing_form_data">
79 <option value="everyday">Once per day at midnight</option>
80 <option value="twicedaily">Twice daily at midnight and noon</option>
81 <option value="everyhour">Once per hour</option>
82 <option value="everyminute">Once per minute</option>
83 <option value="none">None</option>
86 <div class="col-sm-2" >
87 <button class="btn btn-info btn-sm" id="schedule_import_odk_cross_data" >Confirm</button>
90 <div class="form-group">
91 <label class="col-sm-6 control-label">Scheduled Time: </label>
92 <div class="col-sm-6" >
93 <div id="scheduled_odk_cross_import_time">
94 <input type="text" disabled value="Not Set" class="form-control" />
107 <&| /page/info_section.mas, title=>'Progress', collapsible=>1, collapsed=>0, is_subsection=>1, subtitle=>'' &>
109 <div id="testing_div"></div>
111 <div class="panel panel-default">
112 <div class="panel-body">
113 <h3>Summary of Received Plant Status</h3>
114 <div id="odk_cross_plant_status_progress_summary_div">
120 <div class="panel panel-default">
121 <div class="panel-body">
122 <h3>Summary of Received Cross Data</h3>
123 <div id="odk_cross_progress_summary_div">
129 <div class="panel panel-default">
130 <div class="panel-body">
131 <div id="odk_cross_progress_div">
133 <h3>Progress Tree</h3>
134 <input type="text" class="form-control input-sm" id="odk_cross_progress_tree_search" placeholder="Search Across Tree" /><br/>
135 <table class="table table-bordered">
138 <th>All Cross Wishlist Entries-- Crosses Completed -- Lab Actions Completed</th>
144 <div id="odk_cross_progress_tree_div" >[loading...]</div>
162 SMAP ODK NOT IMPLEMENTED
165 <&| /page/info_section.mas, title=>'Phenotype Data: SMAP ODK Application', collapsible=>1, collapsed=>0, is_subsection=>1, subtitle=>'[<a id="upload_fieldbook_phenotypes_link" >Upload Fieldbook Database File</a>]' &>
167 <button class="btn btn-primary btn-sm" id="import_odk_phenotype_data" >Import Phenotype Data from SMAP</button>
178 jQuery(document).ready(function () {
181 url : '/ajax/odk/get_crossing_available_forms',
182 beforeSend: function() {
183 jQuery("#working_modal").modal("show");
185 success: function(response){
186 console.log(response);
187 jQuery("#working_modal").modal("hide");
190 alert(response.error);
192 if (response.success){
195 url : '/ajax/odk/get_crossing_saved_ona_forms',
196 success: function(response_forms){
197 console.log(response_forms);
199 if (response_forms.error){
200 alert(response.error);
202 if (response_forms.success){
203 var form_dropdown_select_html = '<select class="form-control" id="availabe_odk_crossing_forms">';
204 var allowed_forms = response_forms.odk_ona_forms;
205 allowed_forms.push('<% $c->config->{odk_crossing_data_test_form_name} %>');
207 for(var i=0; i<response.forms.length; i++){
208 if (jQuery.inArray(response.forms[i].id_string, allowed_forms) != -1){
209 form_dropdown_select_html = form_dropdown_select_html + '<option value="'+response.forms[i].id+'">'+response.forms[i].id_string+'</option>';
210 form_ids.push(response.forms[i].id);
213 console.log(form_ids);
214 var first_form_id = form_ids[0];
215 form_dropdown_select_html = form_dropdown_select_html + '</select>';
216 jQuery('#import_odk_cross_data_available_forms').html(form_dropdown_select_html);
219 url : '/ajax/odk/get_odk_cross_summary_cached?form_id='+first_form_id,
220 success: function(response){
221 console.log(response);
222 summary = response.summary;
224 html = '<table id="odk_cross_info_status_table" class="table table-hover table-bordered"><thead><tr><th>Cross Information</th><th>Seeds Produced Graphs</th></tr></thead><tbody>';
225 for (var top_level in summary) {
226 if (summary.hasOwnProperty(top_level)) {
227 for (var cross_name in summary[top_level]){
228 if (summary[top_level].hasOwnProperty(cross_name)){
229 html = html + '<tr><td><h3>'+cross_name+'</h3>';
230 var cross = summary[top_level][cross_name];
231 //console.log(cross);
233 for (var activity in cross){
234 if (cross.hasOwnProperty(activity)){
235 html = html + '<b>'+activity + ' ('+cross[activity].length+')</b>: <br/>';
236 for (var i=0; i<cross[activity].length; i++){
237 var action = cross[activity][i];
238 for (var attr in action){
239 if (action.hasOwnProperty(attr)){
240 html = html + ' <small>'+attr + ': ' +action[attr]+"</small><br/>";
243 html = html + ' ----</br>';
245 if (activity == 'seedExtraction'){
246 var date = action['extraction_date'].replace('-','').replace('-','').replace('/','').replace('/','');
247 var datum = { "type":activity, "label":"Total Seeds Extracted", "x_pos":parseInt(date), "y_pos":parseInt(action['total_seeds_extracted']) };
248 plot_data.push(datum);
250 if (activity == 'embryoRescue'){
251 var date = action['embryorescue_date'].replace('-','').replace('-','').replace('/','').replace('/','');
252 var datum = { "type":activity, "label":"Good Seeds", "x_pos":parseInt(date), "y_pos":parseInt(action['good_seeds']) };
253 plot_data.push(datum);
254 var datum = { "type":activity, "label":"Bad Seeds", "x_pos":parseInt(date), "y_pos":parseInt(action['bad_seeds']) };
255 plot_data.push(datum);
256 var datum = { "type":activity, "label":"Embryo Rescued Seeds", "x_pos":parseInt(date), "y_pos":parseInt(action['embryorescue_seeds']) };
257 plot_data.push(datum);
259 if (activity == 'screenhouse_humiditychamber'){
260 var date = action['screenhse_transfer_date'].replace('-','').replace('-','').replace('/','').replace('/','');
261 var datum = { "type":activity, "label":"Screenhouse Humidity Chamber", "x_pos":parseInt(date), "y_pos":1 };
262 plot_data.push(datum);
264 if (activity == 'rooting'){
265 var date = action['rooting_date'].replace('-','').replace('-','').replace('/','').replace('/','');
266 var datum = { "type":activity, "label":"Rooting", "x_pos":parseInt(date), "y_pos":1 };
267 plot_data.push(datum);
269 if (activity == 'hardening'){
270 var date = action['hardening_date'].replace('-','').replace('-','').replace('/','').replace('/','');
271 var datum = { "type":activity, "label":"Hardening", "x_pos":parseInt(date), "y_pos":1 };
272 plot_data.push(datum);
274 if (activity == 'contamination'){
275 var date = action['lab_contamination_date'].replace('-','').replace('-','').replace('/','').replace('/','');
276 var datum = { "type":activity, "label":"Contamination", "x_pos":parseInt(date), "y_pos":1 };
277 plot_data.push(datum);
279 if (activity == 'subculture'){
280 var date = action['subculture_date'].replace('-','').replace('-','').replace('/','').replace('/','');
281 var datum = { "type":activity, "label":"Subcultures Count", "x_pos":parseInt(date), "y_pos":parseInt(action['subcultures_count']) };
282 plot_data.push(datum);
284 if (activity == 'germinating_after_2wks'){
285 var date = action['germinating_2wks_date'].replace('-','').replace('-','').replace('/','').replace('/','');
286 var datum = { "type":activity, "label":"Active Seeds 2weeks", "x_pos":parseInt(date), "y_pos":parseInt(action['actively_2wks']) };
287 plot_data.push(datum);
289 if (activity == 'germinating_after_8weeks'){
290 var date = action['germinating_8wksdate'].replace('-','').replace('-','').replace('/','').replace('/','');
291 var datum = { "type":activity, "label":"Active Seeds 8weeks", "x_pos":parseInt(date), "y_pos":parseInt(action['active_8weeks']) };
292 plot_data.push(datum);
297 //console.log(plot_data);
298 cross_name_clean = cross_name.replace('/', '').replace('(', '').replace(')','');
299 var div_id = encodeURI(cross_name_clean)+'_plot_div';
300 plot_data_fill.push([plot_data, div_id]);
301 html = html + '</td><td><div id="'+div_id+'"></div></td></tr>';
306 html = html + '</tbody></table>';
307 jQuery('#odk_cross_progress_summary_div').html(html);
308 for (var i=0; i<plot_data_fill.length; i++){
309 if (plot_data_fill[i][0].length > 0){
310 SGND3ScatterPlot(plot_data_fill[i][0], plot_data_fill[i][1], "Date of Activity");
313 jQuery('#odk_cross_info_status_table').DataTable({
314 "order": [[ 0, "desc" ]]
317 var plant_status_html = '<table id="odk_cross_plant_status_table" class="table table-hover table-bordered"><thead><tr><th>Plot Name</th><th>Date</th><th>Status</th></tr></thead><tbody>';
318 var plant_status_summary = response.plant_status_summary;
319 console.log(plant_status_summary);
320 for (var plot_name in plant_status_summary){
321 if (plant_status_summary.hasOwnProperty(plot_name)){
323 for (var status_type in plant_status_summary[plot_name]){
325 if (plant_status_summary[plot_name].hasOwnProperty(status_type)){
326 var status = plant_status_summary[plot_name][status_type];
327 //console.log(status);
328 if (status_type == 'status'){
329 plant_status_html = plant_status_html + '<tr><td>' + plot_name + '</td><td>' + status['status_date'] + '</td><td><b>Status:</b><br/>Accession Name: ' + status['status_accession_name'] + '<br/>Trial Name: ' + status['status_trial_name'] + '<br/>User: ' + status['status_user'] + '<br/>Status Location: ' + status['status_location'] + '<br/>Status: ' + status['status_message'] + '<br/>Note: ' + status['status_note'] + '<br/>Image: ' + status['attachment_display_thumb'] + '<br/></td></tr>';
331 if (status_type == 'flowering'){
332 plant_status_html = plant_status_html + '<tr><td>' + plot_name + '</td><td>' + status['FieldActivities/Flowering/flowering_date'] + '</td><td><b>Flowering:</b><br/>Accession Name: ' + status['FieldActivities/Flowering/flowerName'] + '<br/>Plant Sex: ' + status['FieldActivities/Flowering/plantSex'] + '<br/></td></tr>';
336 if (has_status == 0){
337 plant_status_html = plant_status_html+ '<tr><td>' + plot_name + '</td><td></td><td></td></tr>';
341 plant_status_html = plant_status_html + '</tbody></thead>';
342 jQuery('#odk_cross_plant_status_progress_summary_div').html(plant_status_html);
343 jQuery('#odk_cross_plant_status_table').DataTable({
344 "order": [[ 1, "desc" ]]
347 error: function(response){
348 alert("Error retrieving available ODK cross summary");
352 //Load ODK Cross Progress Tree
353 jQuery('#odk_cross_progress_tree_div').jstree({
356 'url' : '/ajax/odk/get_odk_cross_progress_cached?form_id='+first_form_id,
357 'data' : function (node) {
358 return { 'id' : node.id };
361 'themes': { 'name': 'proton', 'responsive': true}
364 "case_insensitive" : true,
366 "plugins" : ["html_data","search","sort"],
369 jQuery("#odk_cross_progress_tree_search").keyup(function() {
370 var v = jQuery("#odk_cross_progress_tree_search").val();
371 jQuery("#odk_cross_progress_tree_div").jstree(true).search(v);
375 error: function(response_forms){
376 alert("Error retrieving saved ODK ONA forms");
382 error: function(response){
383 jQuery("#working_modal").modal("hide");
384 alert("Error retrieving available ODK crossing forms");
389 url : '/ajax/odk/get_crossing_data_cronjobs',
390 beforeSend: function() {
391 jQuery("#working_modal").modal("show");
393 success: function(response){
394 console.log(response);
395 jQuery("#working_modal").modal("hide");
398 alert(response.error);
400 if (response.success){
401 var html = 'Not Set';
402 if (response.entries[0] == '0-59/1 * * * * '){
403 html = '<input type="text" disabled value="Once per minute" class="form-control" />';
405 if (response.entries[0] == '1 0 * * * '){
406 html = '<input type="text" disabled value="Once per day at midnight" class="form-control" />';
408 if (response.entries[0] == '0 * * * * '){
409 html = '<input type="text" disabled value="Once per hour" class="form-control" />';
411 if (response.entries[0] == '0 0,12 * * * '){
412 html = '<input type="text" disabled value="Twice daily at midnight and noon" class="form-control" />';
414 jQuery('#scheduled_odk_cross_import_time').html(html);
417 error: function(response){
418 jQuery("#working_modal").modal("hide");
422 jQuery('#import_odk_phenotype_data').click( function(){
424 url : '/ajax/odk/get_phenotyping_data?form_id='+jQuery('#availabe_odk_phenotyping_forms').val(),
425 beforeSend: function() {
426 jQuery("#working_modal").modal("show");
428 success: function(response){
429 //console.log(response);
430 jQuery("#working_modal").modal("hide");
433 alert(response.error);
435 alert('Not currently working.');
437 error: function(response){
438 jQuery("#working_modal").modal("hide");
439 alert("Error retrieving ODK phenotyping data.");
444 jQuery('#import_odk_cross_data').click( function(){
446 url : '/ajax/odk/get_crossing_data?form_id='+jQuery('#availabe_odk_crossing_forms').val(),
447 beforeSend: function() {
448 jQuery("#working_modal").modal("show");
450 success: function(response){
451 console.log(response);
452 jQuery("#working_modal").modal("hide");
455 alert(response.error);
459 error: function(response){
460 jQuery("#working_modal").modal("hide");
461 alert("Error retrieving ODK crossing data.");
466 jQuery('#schedule_import_odk_cross_data').click( function(){
468 url : '/ajax/odk/schedule_get_crossing_data?form_id='+jQuery('#availabe_odk_crossing_forms').val()+'&timing='+jQuery('#schedule_import_odk_crossing_form_data').val(),
469 beforeSend: function() {
470 jQuery("#working_modal").modal("show");
472 success: function(response){
473 console.log(response);
474 jQuery("#working_modal").modal("hide");
477 alert(response.error);
480 error: function(response){
481 jQuery("#working_modal").modal("hide");
482 alert("Error scheduling import of ODK crossing data.");