added the list of management factor types in controllers
[sgn.git] / mason / breeders_toolbox / manage_odk_data_collection.mas
blob40c77fe2c616324b72ff6fe8dd3d3bf5714d8f7c
2 <%args>
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
8 </%args>
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">
19 <div class="well">
20 <h4>What is ODK?</h4>
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>
23 <ul>
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.
25 </li>
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.
27 </li>
28 </ul>
29 </div>
31 <div class="well">
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>
43                 </div>
44             </div>
45         </form>
46     </div>
47 </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">
53         <div class="row">
54             <div class="col-sm-1">
55                 <span style="font-size:3em;" class="glyphicon glyphicon-transfer"></span>
56             </div>
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>
59                 <br/><br/>
60                 <button class="pull-right btn btn-info btn-sm" id="import_odk_cross_data" >Import Crossing Data from Selected Form on ONA</button>
61             </div>
62         </div>
63     </div>
64 </div>
66 <!--
67 <div class="panel panel-default">
68     <div class="panel-body">
69         <div class="row">
70             <div class="col-sm-1">
71                 <span style="font-size:3em;" class="glyphicon glyphicon-time"></span>
72             </div>
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>
84                             </select>
85                         </div>
86                         <div class="col-sm-2" >
87                             <button class="btn btn-info btn-sm" id="schedule_import_odk_cross_data" >Confirm</button>
88                         </div>
89                     </div>
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" />
95                             </div>
96                         </div>
97                     </div>
98                 </form>
99             </div>
100         </div>
101     </div>
102 </div>
105 </&>
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">
115         [LOADING...]
116         </div>
117     </div>
118 </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">
124         [LOADING...]
125         </div>
126     </div>
127 </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">
136                 <thead>
137                     <tr>
138                         <th>All Cross Wishlist Entries-- Crosses Completed -- Lab Actions Completed</th>
139                     </tr>
140                 </thead>
141                 <tbody>
142                     <tr>
143                         <td>
144                             <div id="odk_cross_progress_tree_div" >[loading...]</div>
145                         </td>
146                     </tr>
147                 </tbody>
148             </table>
150         </div>
151     </div>
152 </div>
154 </&>
157 </&>
159 </div>
161 <!--
162 SMAP ODK NOT IMPLEMENTED 
163 <div class="well">
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>
169 </&>
171 </div>
174 </div>
176 <script>
178 jQuery(document).ready(function () {
180     jQuery.ajax ( {
181         url : '/ajax/odk/get_crossing_available_forms',
182         beforeSend: function() {
183             jQuery("#working_modal").modal("show");
184         },
185         success: function(response){
186             console.log(response);
187             jQuery("#working_modal").modal("hide");
189             if (response.error){
190                 alert(response.error);
191             }
192             if (response.success){
193             
194                 jQuery.ajax ({
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);
201                         }
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} %>');
206                             var form_ids = [];
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);
211                                 }
212                             }
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);
218                             jQuery.ajax ({
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;
223                                     plot_data_fill = [];
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);
232                                                     var plot_data = [];
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 + '&nbsp;&nbsp;&nbsp;&nbsp;<small>'+attr + ': ' +action[attr]+"</small><br/>";
241                                                                     }
242                                                                 }
243                                                                 html = html + '&nbsp;&nbsp;&nbsp;&nbsp;----</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);
249                                                                 }
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);
258                                                                 }
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);
263                                                                 }
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);
268                                                                 }
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);
273                                                                 }
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);
278                                                                 }
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);
283                                                                 }
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);
288                                                                 }
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);
293                                                                 }
294                                                             }
295                                                         }
296                                                     }
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>';
302                                                 }
303                                             }
304                                         }
305                                     }
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");
311                                         }
312                                     }
313                                     jQuery('#odk_cross_info_status_table').DataTable({
314                                         "order": [[ 0, "desc" ]]
315                                     });
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)){
322                                             var has_status = 0;
323                                             for (var status_type in plant_status_summary[plot_name]){
324                                                 has_status = 1;
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>';
330                                                     }
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>';
333                                                     }
334                                                 }
335                                             }
336                                             if (has_status == 0){
337                                                 plant_status_html = plant_status_html+ '<tr><td>' + plot_name + '</td><td></td><td></td></tr>';
338                                             }
339                                         }
340                                     }
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" ]]
345                                     });
346                                 },
347                                 error: function(response){
348                                     alert("Error retrieving available ODK cross summary");
349                                 }
350                             });
352                             //Load ODK Cross Progress Tree
353                             jQuery('#odk_cross_progress_tree_div').jstree({
354                                 "core": {
355                                     'data' : {
356                                         'url' : '/ajax/odk/get_odk_cross_progress_cached?form_id='+first_form_id,
357                                         'data' : function (node) {
358                                             return { 'id' : node.id };
359                                         }
360                                     },
361                                     'themes': { 'name': 'proton', 'responsive': true}
362                                 },
363                                 "search" : {
364                                     "case_insensitive" : true,
365                                 },
366                                 "plugins" : ["html_data","search","sort"],
367                             });
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);
372                             });
373                         }
374                     },
375                     error: function(response_forms){
376                         alert("Error retrieving saved ODK ONA forms");
377                     }
378                 });
379             
380             }
381         },
382         error: function(response){
383             jQuery("#working_modal").modal("hide");
384             alert("Error retrieving available ODK crossing forms");
385         }
386     });
388     jQuery.ajax ( {
389         url : '/ajax/odk/get_crossing_data_cronjobs',
390         beforeSend: function() {
391             jQuery("#working_modal").modal("show");
392         },
393         success: function(response){
394             console.log(response);
395             jQuery("#working_modal").modal("hide");
397             if (response.error){
398                 alert(response.error);
399             }
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" />';
404                 }
405                 if (response.entries[0] == '1 0 * * * '){
406                     html = '<input type="text" disabled value="Once per day at midnight" class="form-control" />';
407                 }
408                 if (response.entries[0] == '0 * * * * '){
409                     html = '<input type="text" disabled value="Once per hour" class="form-control" />';
410                 }
411                 if (response.entries[0] == '0 0,12 * * * '){
412                     html = '<input type="text" disabled value="Twice daily at midnight and noon" class="form-control" />';
413                 }
414                 jQuery('#scheduled_odk_cross_import_time').html(html);
415             }
416         },
417         error: function(response){
418             jQuery("#working_modal").modal("hide");
419         }
420     });
422     jQuery('#import_odk_phenotype_data').click( function(){
423         jQuery.ajax ( {
424             url : '/ajax/odk/get_phenotyping_data?form_id='+jQuery('#availabe_odk_phenotyping_forms').val(),
425             beforeSend: function() {
426                 jQuery("#working_modal").modal("show");
427             },
428             success: function(response){
429                 //console.log(response);
430                 jQuery("#working_modal").modal("hide");
432                 if (response.error){
433                     alert(response.error);
434                 }
435                 alert('Not currently working.');
436             },
437             error: function(response){
438                 jQuery("#working_modal").modal("hide");
439                 alert("Error retrieving ODK phenotyping data.");
440             }
441         });
442     });
443     
444     jQuery('#import_odk_cross_data').click( function(){
445         jQuery.ajax ( {
446             url : '/ajax/odk/get_crossing_data?form_id='+jQuery('#availabe_odk_crossing_forms').val(),
447             beforeSend: function() {
448                 jQuery("#working_modal").modal("show");
449             },
450             success: function(response){
451                 console.log(response);
452                 jQuery("#working_modal").modal("hide");
454                 if (response.error){
455                     alert(response.error);
456                 }
457                 location.reload();
458             },
459             error: function(response){
460                 jQuery("#working_modal").modal("hide");
461                 alert("Error retrieving ODK crossing data.");
462             }
463         });
464     });
466     jQuery('#schedule_import_odk_cross_data').click( function(){
467         jQuery.ajax ( {
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");
471             },
472             success: function(response){
473                 console.log(response);
474                 jQuery("#working_modal").modal("hide");
476                 if (response.error){
477                     alert(response.error);
478                 }
479             },
480             error: function(response){
481                 jQuery("#working_modal").modal("hide");
482                 alert("Error scheduling import of ODK crossing data.");
483             }
484         });
485     });
489 </script>