diff --git a/Capfile b/Capfile index eb67ee33..c56719e1 100644 --- a/Capfile +++ b/Capfile @@ -12,10 +12,12 @@ require 'capistrano/rbenv' require 'capistrano/puma' install_plugin Capistrano::Puma +install_plugin Capistrano::Puma::Systemd install_plugin Capistrano::Puma::Monit require 'capistrano/sidekiq' -require 'capistrano/sidekiq/monit' +install_plugin Capistrano::Sidekiq +install_plugin Capistrano::Sidekiq::Monit require 'whenever/capistrano' diff --git a/app/assets/javascripts/datatable_initialisation.js b/app/assets/javascripts/datatable_initialisation.js new file mode 100644 index 00000000..a661282b --- /dev/null +++ b/app/assets/javascripts/datatable_initialisation.js @@ -0,0 +1,361 @@ +jQuery(function() { + // FREEZERS + $('#freezers').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#freezers').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 3 } + ], + "order": [ 2, 'desc' ] + } ); + + //HERBARIA + $('#herbaria').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#herbaria').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 3 } + ], + "order": [1, 'asc'] + } ); + + // ISOLATES + $('#isolates').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#isolates').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 4, 'desc' ] + } ); + + $('#isolates_no_specimen').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#isolates_no_specimen').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 0, 'asc' ] + } ); + + $('#isolates_duplicates').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#isolates_duplicates').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 0, 'desc' ] + } ); + + // LAB RACKS + $('#lab_racks').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#lab_racks').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 0, 'desc' ] + } ); + + // MARKERS + $('#markers').DataTable( { + "columnDefs": [ + { "orderable": false, "targets": 2 } + ], + "order": [ 7, 'desc' ] + } ); + + // MICRONIC PLATES + $('#micronic_plates').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#micronic_plates').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 6 } + ], + "order": [ 5, 'desc' ] + } ); + + // PLANT PLATES + $('#plant_plates').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#plant_plates').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 2 } + ], + "order": [ 1, 'desc' ] + } ); + + // PRIMERS + $('#primers').DataTable( { + "order": [ 4, 'desc' ], + "columnDefs": [ + { "orderable": false, "targets": 5 } + ] + } ); + + // USERS + $('#users').DataTable( { + "columnDefs": [ + { "orderable": false, "targets": 3 }, + { "orderable": false, "targets": 7 } + ] + } ); + + // CLUSTERS + $('#clusters').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#clusters').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 4, 'desc' ] + } ); + + // CONTIG SEARCHES + $('#contig_searches').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#contig_searches').data('source'), + "columnDefs": [{ + "targets": 3, + "orderable": false + }], + "order": [ 2, 'desc' ] + } ); + + $('#contig_search_results').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#contig_search_results').data('source'), + "columnDefs": [{ + "targets": [1, 2, 5], + "orderable": false + }], + "order": [ 0, 'asc' ] + } ); + + // CONTIGS + $('#contigs').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#contigs').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 4, 'desc' ] + } ); + + $('#contigs-duplicates').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#contigs-duplicates').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 0, 'asc' ] + } ); + + // INDIVIDUAL SEARCHES + $('#individual_searches').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#individual_searches').data('source'), + "columnDefs": [{ + "orderable": false, + "targets": 3 + }], + "order": [ 2, 'desc' ] + } ); + + $('#individual_search_results').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#individual_search_results').data('source'), + "columnDefs": [{ + "orderable": false, + "targets": [1, 6] + }], + "order": [ 0, 'asc' ] + } ); + + // INDIVIDUALS + $('#individuals').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#individuals').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 6 } + ], + "order": [5, 'desc'] + } ); + + // ISSUES + $('#issues').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#issues').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 1 }, + { "orderable": false, "targets": 2 } + ], + "order": [ 3, 'desc' ] + } ); + + // MARKERS SEQUENCE SEARCHES + $('#marker_sequence_searches').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#marker_sequence_searches').data('source'), + "columnDefs": [{ + "orderable": false, + "targets": 3 + }], + "order": [ 2, 'desc' ] + } ); + + $('#marker_sequence_search_results').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#marker_sequence_search_results').data('source'), + "columnDefs": [{ + "orderable": false, + "targets": [1, 3] + }], + "order": [ 0, 'asc' ] + } ); + + // MARKER SEQUENCES + $('#marker_sequences').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#marker_sequences').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 3 } + ], + "order": [ 2, 'desc' ] + } ); + + // MISLABEL ANALYSES + $('#mislabel_analyses').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#mislabel_analyses').data('source'), + "columnDefs": [{ + "orderable": false, + "targets": [1, 4] + }], + "order": [3, 'desc'] + } ); + + $('#mislabel_analysis_results').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#mislabel_analysis_results').data('source'), + "columnDefs": [{ + "orderable": false, + "targets": 6 + }], + "order": [0, 'asc'] + } ); + + // NGS RUNS + $('#ngs_runs').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#ngs_runs').data('source'), + "columnDefs": [{ + "targets": 2, + "orderable": false + }], + "order": [1, 'desc'] + } ); + + $('#ngs_run_results').dataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#ngs_run_results').data('source'), + "sScrollY": document.body.clientHeight * 70 / 100, + "scrollX": true, + scroller: { + loadingIndicator: true, + displayBuffer: 2 + }, + deferRender: true, + "columnDefs": [{ + "targets": 3, + "orderable": false + }], + "order": [0, 'desc'] + } ); + + // PRIMER READS + $('#primer_reads').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#primer_reads').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 4 } + ], + "order": [ 3, 'desc' ] + } ); + + $('#primer_reads-duplicates').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#primer_reads-duplicates').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 4 } + ], + "order": [ 0, 'asc' ] + } ); + + $('#reads_without_contigs').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#reads_without_contigs').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 4 } + ], + "order": [ 3, 'desc' ] + } ); + + // TAXA + $('#associated_individuals').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#associated_individuals').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 6 } + ], + "order": [5, 'desc'] + } ); + + $('#direct_children').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#direct_children').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 0, 'asc' ] + } ); + + $('#orphans').DataTable( { + bProcessing: true, + bServerSide: true, + sAjaxSource: $('#orphans').data('source'), + "columnDefs": [ + { "orderable": false, "targets": 5 } + ], + "order": [ 0, 'asc' ] + } ); +} ); diff --git a/app/assets/javascripts/progress_overview.js b/app/assets/javascripts/progress_overview.js index 7f6704e3..1d17d7e3 100644 --- a/app/assets/javascripts/progress_overview.js +++ b/app/assets/javascripts/progress_overview.js @@ -50,16 +50,28 @@ function changeDownloadButtonStatus() { function drawProgressTree(data) { var parentDiv = document.getElementById("progress_tree"); - var width = parentDiv.clientWidth - 17, // subtract padding and border width - height = 710, - scale = 1, - radius = Math.max(width/2 - 100, 500), - nodeRadius = 2; + var width = parentDiv.clientWidth, + height = 710; - var treeLayout = d3.cluster().size([2 * Math.PI, radius - 100]); + var root = d3.hierarchy(data) + .sort((a, b) => d3.ascending(a.data.scientific_name, b.data.scientific_name)); - var root = treeLayout(d3.hierarchy(data) - .sort((a, b) => d3.ascending(a.data.scientific_name, b.data.scientific_name))); + var maxChildren = 0; + var leaveCnt = 0; + root.descendants().forEach(function(d) { + if (!d.children){ + maxChildren = Math.max(maxChildren, d.data.size); + leaveCnt++; + } + }) + + var radius = Math.max(width/2, leaveCnt * 30 / (2 * Math.PI)); // Calculate tree radius from number of leave nodes with a minimum distance of 30 + var scale = height / ( 2 * radius); + + var treeLayout = d3.cluster() + .size([2 * Math.PI, radius - 150]); + + treeLayout(root); var svg = d3.select('#progress_tree') .append("svg") @@ -82,13 +94,13 @@ function drawProgressTree(data) { svg.call(zoom); // Trigger initial zoom with an initial transform - zoom.transform(svg, d3.zoomIdentity.translate(width / 2, radius).scale(scale)); + zoom.transform(svg, d3.zoomIdentity.translate($("#progress_svg").width() / 2, height/2).scale(scale)); // Initially zoom out to show full tree // Button to reset zoom and position d3.select("#reset_zoom") .on("click", function() { var current_width = $("#progress_svg").width(); - zoom.transform(svg, d3.zoomIdentity.translate(current_width / 2, radius).scale(scale)); + zoom.transform(svg, d3.zoomIdentity.translate(current_width / 2, height/2).scale(scale)); }); enableButton($('#reset_zoom')); @@ -152,11 +164,13 @@ function drawProgressTree(data) { }) .on("mousemove", function(d) { var finished_percent = d.data.size === 0 ? '' : " (" + ((d.data.finished_size / d.data.size) * 100).toFixed(2) + "%)"; + var sidebar_width = $("#sidebar_progress_tree").width(); + tooltip .html(d.data.scientific_name + ":
" + d.data.size + " species (incl. subspecies)
" + d.data.finished_size + " finished" + finished_percent) - .style("left", (d3.event.pageX - parentDiv.offsetLeft + 10) + "px") - .style("top", (d3.event.pageY - parentDiv.offsetTop + 20) + "px"); + .style("left", (d3.event.pageX - document.getElementById('chart_column').offsetLeft + 20) + "px") + .style("top", (d3.event.pageY - document.getElementById('chart_column').offsetTop - document.getElementById('progress_tree').offsetTop + 28) + "px"); }) .on("mouseout", function mouseout() { tooltip.transition() @@ -168,8 +182,14 @@ function drawProgressTree(data) { .style("font-weight", 'normal'); }); + var nodeRadiusMin = 4; + var nodeRadiusMax = 40; + var nodeSizeScale = d3.scaleLinear() + .domain([0, maxChildren]) + .range([nodeRadiusMin, nodeRadiusMax]); + nodeEnter.append('circle') - .attr('r', d => d.children ? nodeRadius : ((d.data.size / 5) + 1)) + .attr('r', d => d.children ? nodeRadiusMin : nodeSizeScale(d.data.size)) .style("stroke", "#555") .attr("fill", function(d) { return nodeColor((d.data.finished_size / d.data.size) * 100) }) .attr("transform", d => ` @@ -187,7 +207,7 @@ function drawProgressTree(data) { `) .attr("dy", "0.31em") .attr("x", function(d) { - r = d.children ? nodeRadius : ((d.data.size / 5) + 1); + r = d.children ? nodeRadiusMin : nodeSizeScale(d.data.size); return d.x < Math.PI === !d.children ? (r + 6) : (0 - r - 6); }) .attr("text-anchor", d => d.x < Math.PI === !d.children ? "start" : "end") diff --git a/app/assets/javascripts/selects_with_select2.js b/app/assets/javascripts/selects_with_select2.js new file mode 100644 index 00000000..3fbdc26b --- /dev/null +++ b/app/assets/javascripts/selects_with_select2.js @@ -0,0 +1,168 @@ +jQuery(function() { + // CLUSTERS + $('#cluster_isolate_id').select2((select2AutocompleteOptions("/isolates/filter", "an isolate"))); + + // CONTIGS + $('#contig_isolate_id').select2((select2AutocompleteOptions("/isolates/filter", "an isolate"))); + $('#contig_marker_id').select2((select2AutocompleteOptions("/markers/filter", "a marker"))); + $('#contig_marker_sequence_id').select2((select2AutocompleteOptions("/marker_sequences/filter", "a marker sequence"))); + $('#contig_project_ids').select2(select2MultiselectOptions); + + // CONTIG SEARCHES + $('#contig_search_name').select2((select2AutocompleteOptions("/contigs/filter", "a contig"))); + $('#contig_search_marker').select2(select2SingleSelectOptions('a marker')); + $('#contig_search_specimen').select2((select2AutocompleteOptions("/individuals/filter", "a specimen"))); + $('#contig_search_taxon').select2((select2AutocompleteOptions("/taxa/filter", "a taxon"))); + $('#contig_search_verified_by').select2(select2SingleSelectOptions('a user')); + + // FREEZERS + $('#freezer_lab_id').select2(select2SingleSelectOptions('a lab')); + $('#freezer_project_ids').select2(select2MultiselectOptions); + + // INDIVIDUALS + $('#individual_taxon_id').select2((select2AutocompleteOptions("/taxa/filter", "a taxon"))); + $('#individual_herbarium_id').select2(select2SingleSelectOptions('an herbarium')); + $('#individual_tissue_id').select2(select2SingleSelectOptions('a tissue type')); + $('#individual_project_ids').select2(select2MultiselectOptions); + + // INDIVIDUAL SEARCHES + $('#individual_search_specimen_id').select2((select2AutocompleteOptions("/individuals/filter", "a specimen"))); + $('#individual_search_herbarium_id').select2(select2SingleSelectOptions('an herbarium')); + $('#individual_search_taxon').select2((select2AutocompleteOptions("/taxa/filter", "a taxon"))); + + // ISOLATES + $('#isolate_project_ids').select2(select2MultiselectOptions); + $('#isolate_individual_id').select2((select2AutocompleteOptions("/individuals/filter", "a specimen"))); + $('#isolate_tissue_id').select2(select2SingleSelectOptions('a tissue type')); + $('#isolate_plant_plate_id').select2(select2SingleSelectOptions('a plate')); + $('#isolate_user_id').select2(select2SingleSelectOptions('a user')); + + // ISSUES + $('#issue_project_ids').select2(select2MultiselectOptions); + + // LAB RACKS + $('#lab_rack_shelf_id').select2(select2SingleSelectOptions('a shelf')); + $('#lab_rack_project_ids').select2(select2MultiselectOptions); + + // LABS + $('#lab_project_ids').select2(select2MultiselectOptions); + + // MARKERS + $('#marker_project_ids').select2(select2MultiselectOptions); + + // MARKER SEQUENCES + $('#marker_sequence_isolate_id').select2((select2AutocompleteOptions("/isolates/filter", "an isolate"))); + $('#marker_sequence_marker_id').select2(select2SingleSelectOptions('a marker')); + $('#marker_sequence_project_ids').select2(select2MultiselectOptions); + + // MARKER SEQUENCE SEARCHES + $('#marker_sequence_search_name').select2((select2AutocompleteOptions("/marker_sequences/filter", "a marker sequence name"))); + $('#marker_sequence_search_marker').select2(select2SingleSelectOptions('a marker')); + $('#marker_sequence_search_specimen').select2((select2AutocompleteOptions("/individuals/filter", "a specimen"))); + $('#marker_sequence_search_taxon').select2((select2AutocompleteOptions("/taxa/filter", "a taxon"))); + $('#marker_sequence_search_verified_by').select2(select2SingleSelectOptions('a user')); + + // MICRONIC PLATES + $('#micronic_plate_lab_rack_id').select2(select2SingleSelectOptions('a rack')); + $('#micronic_plate_project_ids').select2(select2MultiselectOptions); + + // NGS RUNS + $('#ngs_run_taxon_id').select2((select2AutocompleteOptions("/taxa/filter", "a taxon"))); + + // PLANT PLATES + $('#plant_plate_project_ids').select2(select2MultiselectOptions); + + // PRIMER READS + $('#primer_read_contig_id').select2((select2AutocompleteOptions("/contigs/filter", "a contig"))); + $('#primer_read_project_ids').select2(select2MultiselectOptions); + + // PRIMERS + $('#primer_marker_id').select2(select2SingleSelectOptions('a marker')); + $('#primer_project_ids').select2(select2MultiselectOptions); + + // PROJECTS + $('#project_user_ids').select2(select2MultiselectOptions); + $( '#associated_project_ids').select2(select2MultiselectOptions); + $('#query_associated_taxon').select2((select2AutocompleteOptions("/taxa/filter", "a taxon"))); + + // SHELVES + $('#shelf_project_ids').select2(select2MultiselectOptions); + + // TAXA + $( "#taxon_taxonomic_rank" ).select2(select2SingleSelectOptions('a rank')); + $( "#taxon_parent_id" ).select2(select2AutocompleteOptions("/taxa/filter", "a taxon")); + $('#taxon_project_ids').select2(select2MultiselectOptions); + + $("#taxonomy_root_select").select2({ + theme: "bootstrap", + placeholder: 'Select a taxon', + minimumResultsForSearch: 15, + allowClear: false, + width: 'auto' + }); + + $('#taxon_search').select2(select2AutocompleteOptions("/taxa/filter", "a taxon", 'auto')); + + // USERS + $("#user_lab_id").select2(select2SingleSelectOptions('a lab')); + $("#user_responsibility_ids").select2(select2MultiselectOptions); + $("#user_project_ids").select2(select2MultiselectOptions); + + // DEPRECATED + $('#family_project_ids').select2(select2MultiselectOptions); + + $('#order_project_ids').select2(select2MultiselectOptions); + + $('#species_project_ids').select2(select2MultiselectOptions); + + $('#higher_order_taxon_marker_ids').select2(select2MultiselectOptions); + + $('#higher_order_taxon_project_ids').select2(select2MultiselectOptions); +}); + +let select2MultiselectOptions = { + theme: "bootstrap", + width: '190px' +}; + +function select2SingleSelectOptions(recordName, width='190px') { + return { + theme: "bootstrap", + placeholder: 'Select ' + recordName, + minimumResultsForSearch: 15, + allowClear: true, + width: width + } +} + +function select2AutocompleteOptions(filter_url, recordName, width='190px') { + return { + theme: "bootstrap", + minimumResultsForSearch: 15, + placeholder: 'Select ' + recordName, + allowClear: true, + minimumInputLength: 2, + width: width, + ajax: { + url: filter_url, + delay: 400, + data: function (params) { + return { + term: params.term + }; + }, + processResults: function (data) { + var results = []; + $.each(data, function(index, item){ + results.push({ + id: item.id, + text: item.name + }); + }); + return { + results: results + }; + }, + }, + }; +} diff --git a/app/assets/javascripts/taxa.js b/app/assets/javascripts/taxa.js index d9a9f038..6162a235 100644 --- a/app/assets/javascripts/taxa.js +++ b/app/assets/javascripts/taxa.js @@ -2,54 +2,35 @@ jQuery(function() { if (document.getElementById("taxonomy_tree") != null) { initialize_buttons(); - $("#taxonomy_root_select").on("change", () => $.ajax({ - type: "GET", - contentType: "application/json; charset=utf-8", - url: 'taxa/taxonomy_tree', - dataType: 'json', - data: { - root_id: $('#taxonomy_root_select option:selected').val() - }, - success: function (data) { - remove_selected_taxon_info(); - deleteVisualization('#taxonomy_tree'); + loadTaxonomy(); - drawTaxonomy(data[0]); - }, - error: function (_result) { - console.error("Error getting data."); - } - })); + $("#taxonomy_root_select").on("change", () => loadTaxonomy()); } +}); - $('#taxon_parent_name').autocomplete({ - source: $('#taxon_parent_name').data('autocomplete-source')}); - - $('#taxon_project_ids').chosen({ - allow_single_deselect: true, - no_results_text: 'No results matched' - }); - - $('#taxon_search').autocomplete({ - source: $('#taxon_search').data('autocomplete-source')}); - - $('#orphans').DataTable({ - bProcessing: true, - bServerSide: true, - sAjaxSource: $('#orphans').data('source'), - "columnDefs": [ - { "orderable": false, "targets": 5 } - ], - "order": [ 0, 'asc' ] +function loadTaxonomy() { + $.ajax({ + type: "GET", + contentType: "application/json; charset=utf-8", + url: 'taxa/taxonomy_tree', + dataType: 'json', + data: { + root_id: $('#taxonomy_root_select option:selected').val() + }, + success: function (data) { + remove_selected_taxon_info(); + deleteVisualization('#taxonomy_tree'); + + drawTaxonomy(data[0]); + }, + error: function (_result) { + console.error("Error getting data."); + } }); -}); +} function initialize_buttons() { - disableButton($("#center_root"), "Please load a taxonomy first"); - disableButton($("#reset_tree_pos"), "Please load a taxonomy first"); - disableButton($("#center_selected_node"), "Please select a taxon first"); - disableButton($("#edit_taxon"), "Please select a taxon first"); disableButton($("#delete_taxon"), "Please select a taxon first"); } @@ -72,6 +53,7 @@ function drawTaxonomy(data) { scale = 1; var selected_node = null; + var selected_circle = null; // Append the SVG object to the parent div var svg = d3.select('#taxonomy_tree') @@ -101,8 +83,8 @@ function drawTaxonomy(data) { duration = 750, root; - // // Declares a tree layout and assigns the size - var treemap = d3.tree().size([width, height]); + // Declares a tree layout and assigns the size + var treemap = d3.tree().separation(function(a, b) { return a.parent == b.parent ? 2.5 : 2; }).nodeSize([2 * nodeRadius, 4 * nodeRadius]); // Assigns the data to a hierarchy using parent-child relationships root = d3.hierarchy(data, function(d) { @@ -115,21 +97,12 @@ function drawTaxonomy(data) { update(root); - centerNode(root); - - enableButton($("#center_root"), "Center root node"); - enableButton($("#reset_tree_pos"), "Align tree to top left"); - - // Button to reset zoom and reset tree to top left - d3.select("#reset_tree_pos") - .on("click", function() { - zoom.transform(svg, d3.zoomIdentity.translate(margin.left, margin.top).scale(scale)); - }); + alignTreeLeft(root); // Button to reset zoom and center root node - d3.select("#center_root") + d3.select("#reset_position") .on("click", function() { - centerNode(root); + alignTreeLeft(root); }); // Button to reset zoom and center root node @@ -140,18 +113,12 @@ function drawTaxonomy(data) { } }); - d3.select('#start_search') - .on("click", function() { startTaxonSearch() }); - - document.getElementById('taxon_search') - .addEventListener("keydown", function (e) { - if (e.code === "Enter") { - startTaxonSearch(); - } + $('#taxon_search').on('select2:select', function (e) { + startTaxonSearch(); }); function startTaxonSearch() { - var taxon_name = document.getElementById('taxon_search').value; + var taxon_name = $('#taxon_search').select2('data')[0].text; $.ajax({ type: "GET", @@ -170,23 +137,8 @@ function drawTaxonomy(data) { } function update(source) { - var levelHeight = [1]; - var childCount = function(level, n) { - if (n.children && n.children.length > 0) { - if (levelHeight.length <= level + 1) levelHeight.push(0); - - levelHeight[level + 1] += n.children.length; - n.children.forEach(function(d) { - childCount(level + 1, d); - }); - } - }; - childCount(0, root); - var newHeight = d3.max(levelHeight) === 2 ? 2 * 50 + (25 * levelHeight.length) : d3.max(levelHeight) * 50; // Account for diagonals in height calculation - - treemap = treemap.size([newHeight, width]); - - treeData = treemap(root); + // Assigns the x and y position for the nodes + var treeData = treemap(root); // Compute the new tree layout. var nodes = treeData.descendants(), @@ -249,29 +201,7 @@ function drawTaxonomy(data) { .attr("fill-opacity", 1) .style('font', '14px sans-serif') .on('click', function(d) { - // Display taxon info in top left div - var text = "Scientific name: " + htmlSafe(d.data.scientific_name) + "
"; - if (d.data.taxonomic_rank) text += "Taxonomic rank: " + htmlSafe(d.data.taxonomic_rank) + "
"; - if (d.data.synonym) text += "Synonym: " + htmlSafe(d.data.synonym) + "
"; - if (d.data.common_name) text += "Common name: " + htmlSafe(d.data.common_name) + "
"; - if (d.data.author) text += "Author: " + htmlSafe(d.data.author) + "
"; - if (d.data.comment) text += "Comment: " + htmlSafe(d.data.comment) + "
"; - taxon_text.html(text); - - // Set correct taxon edit and destroy links and enable buttons - var taxon_edit_link = d3.select('#edit_taxon').attr('href').replace(/(.*\/)(\d+)(\/.*)/, "$1" + d.data.id + "$3"); - d3.select('#edit_taxon').attr('href', taxon_edit_link); - enableButton($('#edit_taxon'), 'Edit entry in a new tab'); - - var taxon_delete_link = d3.select('#delete_taxon').attr('href').replace(/(.*\/)(\d+)/, "$1" + d.data.id); - d3.select('#delete_taxon').attr('href', taxon_delete_link); - enableButton($('#delete_taxon'), 'Delete taxon entry'); - - selected_node = d; - enableButton($('#center_selected_node'), 'Center currently selected node'); - - // Display list of specimen associated with this taxon - display_specimen_Data(d); + selectNode(d, this); }); // UPDATE @@ -379,6 +309,16 @@ function drawTaxonomy(data) { }.bind(this)) : toggle(d); } + function alignTreeLeft(root) { + x = margin.left; + y = -root.x0 + height / 2; + + d3.select('g').transition() + .duration(duration) + .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); + zoom.transform(svg, d3.zoomIdentity.translate(x, y).scale(scale)); + } + function centerNode(source) { x = -source.y0; y = -source.x0; @@ -451,6 +391,52 @@ function drawTaxonomy(data) { return promise; //return a promise if async. requests } + function selectNode(d, current_circle) { + // Display taxon info in top left div + var text = "Scientific name: " + htmlSafe(d.data.scientific_name) + "
"; + if (d.data.taxonomic_rank) text += "Taxonomic rank: " + htmlSafe(d.data.taxonomic_rank) + "
"; + if (d.data.synonym) text += "Synonym: " + htmlSafe(d.data.synonym) + "
"; + if (d.data.common_name) text += "Common name: " + htmlSafe(d.data.common_name) + "
"; + if (d.data.author) text += "Author: " + htmlSafe(d.data.author) + "
"; + if (d.data.comment) text += "Comment: " + htmlSafe(d.data.comment) + "
"; + taxon_text.html(text); + + // Set correct taxon edit and destroy links and enable buttons + var taxon_edit_link = d3.select('#edit_taxon').attr('href').replace(/(.*\/)(\d+)(\/.*)/, "$1" + d.data.id + "$3"); + d3.select('#edit_taxon').attr('href', taxon_edit_link); + enableButton($('#edit_taxon'), 'Edit entry in a new tab'); + + var taxon_delete_link = d3.select('#delete_taxon').attr('href').replace(/(.*\/)(\d+)/, "$1" + d.data.id); + d3.select('#delete_taxon').attr('href', taxon_delete_link); + enableButton($('#delete_taxon'), 'Delete taxon entry'); + + selected_node = d; + enableButton($('#center_selected_node'), 'Center currently selected node'); + + // Reset previously selected circle to normal view if one was selected + if (selected_circle) { + d3.select(selected_circle) + .style("stroke-width", '1px') + .style("font-weight", 'normal'); + + d3.select(selected_circle.parentNode).selectAll("circle") + .style("fill", function (d) { + return d.data.has_children ? "lightgrey" : "#fff"; + }); + } + + selected_circle = current_circle; + d3.select(selected_circle) + .style("stroke-width", '2px') + .style("font-weight", 'bold'); + + d3.select(selected_circle.parentNode).selectAll("circle") + .style("fill", '#616161'); + + // Display list of specimen associated with this taxon + display_specimen_Data(d); + } + function display_specimen_Data(d) { $.ajax({ url: "taxa/" + d.data.id + "/associated_specimen", diff --git a/app/controllers/taxa_controller.rb b/app/controllers/taxa_controller.rb index 9e7f4678..45eaa215 100644 --- a/app/controllers/taxa_controller.rb +++ b/app/controllers/taxa_controller.rb @@ -32,17 +32,18 @@ def show_individuals end end - def filter - @taxa = Taxon.where('scientific_name ILIKE ?', "%#{params[:term]}%").in_project(current_project_id).order(:scientific_name).limit(100) - size = Taxon.where('scientific_name ILIKE ?', "%#{params[:term]}%").in_project(current_project_id).order(:scientific_name).size - - if size > 100 - render json: @taxa.map(&:scientific_name).push("and #{size} more...") - else - render json: @taxa.map(&:scientific_name) + def show_children + respond_to do |format| + format.html + format.json { render json: TaxonDatatable.new(view_context, params[:id], current_project_id) } end end + def filter + @taxa = Taxon.where('scientific_name ILIKE ?', "%#{params[:term]}%").in_project(current_project_id).order(:scientific_name) + render json: @taxa.map{ |taxon| {:id=> taxon.id, :name => taxon.scientific_name }} + end + def export_as_csv authorize! :export_as_csv, :taxon @@ -54,7 +55,7 @@ def export_as_csv def orphans respond_to do |format| format.html - format.json { render json: OrphanedTaxaDatatable.new(view_context, current_project_id) } + format.json { render json: TaxonDatatable.new(view_context, nil, current_project_id) } end end diff --git a/app/datatables/taxon_datatable.rb b/app/datatables/taxon_datatable.rb new file mode 100644 index 00000000..8bfd8eae --- /dev/null +++ b/app/datatables/taxon_datatable.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +class TaxonDatatable + include Rails.application.routes.url_helpers + + delegate :url_helpers, to: 'Rails.application.routes' + delegate :params, :link_to, :h, to: :@view + + def initialize(view, parent_id, current_default_project) + @view = view + @parent_id = parent_id + @current_default_project = current_default_project + end + + def as_json(_options = {}) + { + sEcho: params[:sEcho].to_i, + iTotalRecords: Taxon.in_project(@current_default_project).count, + iTotalDisplayRecords: taxa.total_entries, + aaData: data + } + end + + private + + def data + taxa.map do |taxon| + [ + link_to(taxon.scientific_name, edit_taxon_path(taxon)), + taxon.synonym, + taxon.common_name, + taxon.human_taxonomic_rank, + taxon.updated_at.in_time_zone('CET').strftime('%Y-%m-%d %H:%M:%S'), + link_to('Delete', taxon, method: :delete, data: { confirm: 'Are you sure?' }) + ] + end + end + + def taxa + @taxa ||= fetch_taxa + end + + def fetch_taxa + if @parent_id + taxa = Taxon.find(@parent_id)&.children&.in_project(@current_default_project).order("#{sort_column} #{sort_direction}") + else + taxa = Taxon.orphans.in_project(@current_default_project).order("#{sort_column} #{sort_direction}") + end + + taxa = taxa.page(page).per_page(per_page) + + if params[:sSearch].present? + taxa = taxa.where('taxa.scientific_name ILIKE :search OR taxa.synonym ILIKE :search +OR taxa.common_name ILIKE :search', search: "%#{params[:sSearch]}%") + end + + taxa + end + + def page + params[:iDisplayStart].to_i / per_page + 1 + end + + def per_page + params[:iDisplayLength].to_i.positive? ? params[:iDisplayLength].to_i : 10 + end + + def sort_column + columns = %w[taxa.scientific_name taxa.synonym taxa.common_name taxa.taxonomic_rank taxa.updated_at] + columns[params[:iSortCol_0].to_i] + end + + def sort_direction + params[:sSortDir_0] == 'desc' ? 'desc' : 'asc' + end +end diff --git a/app/models/taxon.rb b/app/models/taxon.rb index fecd802f..37264b60 100644 --- a/app/models/taxon.rb +++ b/app/models/taxon.rb @@ -2,10 +2,10 @@ class Taxon < ApplicationRecord extend Import include ProjectRecord - has_many :individuals - has_many :ngs_runs + has_many :individuals, dependent: :nullify + has_many :ngs_runs, dependent: :nullify - has_ancestry cache_depth: true, counter_cache: true + has_ancestry cache_depth: true, counter_cache: true, orphan_strategy: :adopt validates_presence_of :scientific_name validates_uniqueness_of :scientific_name @@ -33,7 +33,7 @@ def self.subtree_json(project_id, parent_id=nil, root_id=nil) children: children} end.to_json else - Taxon.find(root_id).subtree.to_depth(1).order(:position, :scientific_name) + Taxon.find(root_id).subtree.to_depth(3).order(:position, :scientific_name) .in_project(project_id).arrange_serializable do |parent, children| { id: parent.id, scientific_name: parent.scientific_name, diff --git a/app/views/clusters/_form.html.erb b/app/views/clusters/_form.html.erb index 4ca42be7..ec504f95 100644 --- a/app/views/clusters/_form.html.erb +++ b/app/views/clusters/_form.html.erb @@ -51,7 +51,7 @@ <% if @cluster.isolate %> <%= link_to '', edit_isolate_path(@cluster.isolate), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.text_field :isolate_name , data: { autocomplete_source: filter_isolates_path } , class: 'form-control'%> + <%= f.collection_select :isolate_id, Isolate.order(:display_name), :id, :display_name, { include_blank: true }, { class:"form-control" } %>
@@ -59,7 +59,7 @@ <% if @cluster.marker %> <%= link_to '', edit_marker_path(@cluster.marker), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.collection_select(:marker_id, Marker.all, :id, :name, { include_blank: '' }, { class: 'form-control' }) %> + <%= f.collection_select(:marker_id, Marker.all, :id, :name, { include_blank: true }, { class: 'form-control' }) %>
<%= f.submit 'Update', :class => 'btn btn-default' %> diff --git a/app/views/contig_searches/_form.html.erb b/app/views/contig_searches/_form.html.erb index 42af9e6d..783018b6 100644 --- a/app/views/contig_searches/_form.html.erb +++ b/app/views/contig_searches/_form.html.erb @@ -16,7 +16,7 @@
<%= f.label :name, 'Contig name' %>
- <%= f.text_field :name, data: { autocomplete_source: filter_contigs_path }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :name, Contig.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>

@@ -39,7 +39,7 @@
<%= f.label :verified_by %>
- <%= f.text_field :verified_by, data: { autocomplete_source: User.order(:name).map(&:name) }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :verified_by, User.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>

@@ -54,17 +54,17 @@
<%= f.label :marker %>
- <%= f.text_field :marker, data: { autocomplete_source: Marker.order(:name).map(&:name) }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :marker, Marker.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>
<%= f.label :specimen %>
- <%= f.text_field :specimen, data: { autocomplete_source: filter_individuals_path(format: 'json') }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :specimen, Individual.order(:specimen_id), :id, :specimen_id, { include_blank: true }, { class:"form-control" } %>
<%= f.label :taxon, 'Associated Taxon' %>
- <%= f.text_field :taxon, data: { autocomplete_source: filter_taxa_path }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :taxon, Taxon.order(:scientific_name), :id, :scientific_name, { include_blank: true }, { class:"form-control" } %>
diff --git a/app/views/contigs/_form.html.erb b/app/views/contigs/_form.html.erb index fdab6529..866f3eb5 100644 --- a/app/views/contigs/_form.html.erb +++ b/app/views/contigs/_form.html.erb @@ -36,7 +36,7 @@ <% if @contig.isolate %> <%= link_to '', edit_isolate_path(@contig.isolate), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.text_field :isolate_name , data: { autocomplete_source: filter_isolates_path } , class: 'form-control'%> + <%= f.collection_select :isolate_id, Isolate.order(:display_name), :id, :display_name, { include_blank: true }, { class:"form-control" } %>
@@ -44,7 +44,7 @@ <% if @contig.marker %> <%= link_to '', edit_marker_path(@contig.marker), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.collection_select(:marker_id, Marker.all, :id, :name, { include_blank: '' }, { class: 'form-control' }) %> + <%= f.collection_select(:marker_id, Marker.all, :id, :name, { include_blank: true }, { class: 'form-control' }) %>
@@ -52,7 +52,7 @@ <% if @contig.marker_sequence %> <%= link_to '', edit_marker_sequence_path(@contig.marker_sequence), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.text_field :marker_sequence_name , data: { autocomplete_source: filter_marker_sequences_path } , class: 'form-control'%> + <%= f.collection_select :marker_sequence_id, MarkerSequence.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>
diff --git a/app/views/freezers/_form.html.erb b/app/views/freezers/_form.html.erb index c1e98673..4bc087db 100644 --- a/app/views/freezers/_form.html.erb +++ b/app/views/freezers/_form.html.erb @@ -11,7 +11,7 @@
- <%= f.label 'Lab' %> + <%= f.label :lab_id, 'Lab' %> <%= f.collection_select(:lab_id, Lab.all, :id, :labcode, {}, { class: 'form-control' }) %>
diff --git a/app/views/individual_searches/_form.html.erb b/app/views/individual_searches/_form.html.erb index 78ee28d2..83bb22cb 100644 --- a/app/views/individual_searches/_form.html.erb +++ b/app/views/individual_searches/_form.html.erb @@ -16,7 +16,7 @@
<%= f.label :specimen_id, 'Specimen ID' %>
- <%= f.text_field :specimen_id, data: { autocomplete_source: filter_individuals_path }, class: 'form-control' %> + <%= f.collection_select :specimen_id, Individual.order(:specimen_id), :id, :specimen_id, { include_blank: true }, { class:"form-control" } %>
<%= f.label :DNA_bank_id, 'Associated DNA Bank ID' %>
@@ -54,13 +54,13 @@

- <%= f.label :herbarium, 'Herbarium (Acronym)' %>
- <%= f.text_field :herbarium, data: { autocomplete_source: Herbarium.order(:acronym).map(&:acronym) }, class: 'form-control' %> + <%= f.label :herbarium, 'Herbarium' %>
+ <%= f.collection_select :herbarium, Herbarium.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>

<%= f.label :taxon, 'Associated Taxon' %>
- <%= f.text_field :taxon, data: { autocomplete_source: filter_taxa_path }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :taxon, Taxon.order(:scientific_name), :id, :scientific_name, { include_blank: true }, { class:"form-control" } %>

<%= f.submit "Search", class: 'btn btn-default'%>
diff --git a/app/views/individuals/_form.html.erb b/app/views/individuals/_form.html.erb index e6eabad8..4b6d8360 100644 --- a/app/views/individuals/_form.html.erb +++ b/app/views/individuals/_form.html.erb @@ -40,24 +40,24 @@
- <%= f.label 'Parent Taxon' %> + <%= f.label :taxon_id, 'Parent Taxon' %> <% if @individual.taxon %> <%= link_to '', edit_taxon_path(@individual.taxon), :class => 'glyphicon glyphicon-share-alt', :title => "go to #{@individual.taxon.scientific_name} " %> <% end %> - <%= f.text_field :taxon_name, data: { autocomplete_source: filter_taxa_path }, class: 'form-control'%> + <%= f.collection_select :taxon_id, Taxon.order(:scientific_name), :id, :scientific_name, { include_blank: true }, { class:"form-control" } %>
- <%= f.label 'Herbarium' %> + <%= f.label :herbarium_id, 'Herbarium' %> <% if @individual.herbarium %> <%= link_to '', edit_herbarium_path(@individual.herbarium), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.collection_select(:herbarium_id, Herbarium.all, :id, :name, { include_blank: '' }, { class: 'form-control' }) %> + <%= f.collection_select(:herbarium_id, Herbarium.all, :id, :name, {}, { class: 'form-control' }) %>
<%= f.label :tissue_id, 'Tissue type' %> - <%= f.collection_select(:tissue_id, Tissue.all.order(:name), :id, :name, { :include_blank => '' }, { class: 'form-control' }) %> + <%= f.collection_select(:tissue_id, Tissue.all.order(:name), :id, :name, {}, { class: 'form-control' }) %>
diff --git a/app/views/isolates/_form.html.erb b/app/views/isolates/_form.html.erb index c532aa85..7ea11894 100644 --- a/app/views/isolates/_form.html.erb +++ b/app/views/isolates/_form.html.erb @@ -44,17 +44,17 @@ <% if @isolate.individual %> <%= link_to '', edit_individual_path(@isolate.individual), :class => 'glyphicon glyphicon-share-alt', :title => "go to #{@isolate.individual.specimen_id} " %> <% end %> - <%= f.text_field :individual_name, data: {autocomplete_source: filter_individuals_path}, class: 'form-control' %> + <%= f.collection_select :individual_id, Individual.order(:specimen_id), :id, :specimen_id, { include_blank: true }, { class:"form-control" } %>
<%= f.label :tissue_id, 'Tissue type' %> - <%= f.collection_select(:tissue_id, Tissue.all.order(:name), :id, :name, { :include_blank => '' }, { class: 'form-control' }) %> + <%= f.collection_select(:tissue_id, Tissue.all.order(:name), :id, :name, { :include_blank => true }, { class: 'form-control' }) %>
<%= f.label :plant_plate_id, 'Plate (Tissue)' %> - <%= f.collection_select(:plant_plate_id, PlantPlate.all.order(:name), :id, :name, { :include_blank => '' }, { class: 'form-control' }) %> + <%= f.collection_select(:plant_plate_id, PlantPlate.all.order(:name), :id, :name, { :include_blank => true }, { class: 'form-control' }) %>
@@ -69,7 +69,7 @@
<%= f.label :user_id, 'Isolated by' %> - <%= f.collection_select(:user_id, User.all.order(:name), :id, :name, { :include_blank => '' }, { class: 'form-control' }) %> + <%= f.collection_select(:user_id, User.all.order(:name), :id, :name, { :include_blank => true }, { class: 'form-control' }) %> <%= f.label :isolation_date, 'on' %>
<%= f.text_field(:isolation_date, class: 'form-control') %>
diff --git a/app/views/marker_sequence_searches/_form.html.erb b/app/views/marker_sequence_searches/_form.html.erb index c61c57cf..7b4d8def 100644 --- a/app/views/marker_sequence_searches/_form.html.erb +++ b/app/views/marker_sequence_searches/_form.html.erb @@ -15,7 +15,7 @@
<%= f.label :name, 'Marker sequence name' %>
- <%= f.text_field :name, data: { autocomplete_source: filter_contigs_path }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :name, MarkerSequence.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>

@@ -28,7 +28,7 @@
<%= f.label :verified_by %>
- <%= f.text_field :verified_by, data: { autocomplete_source: User.order(:name).map(&:name) }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :verified_by, User.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>

@@ -53,17 +53,17 @@
<%= f.label :marker %>
- <%= f.text_field :marker, data: { autocomplete_source: Marker.order(:name).map(&:name) }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :marker, Marker.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>
<%= f.label :specimen %>
- <%= f.text_field :specimen, data: { autocomplete_source: filter_individuals_path(format: 'json') }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :specimen, Individual.order(:specimen_id), :id, :specimen_id, { include_blank: true }, { class:"form-control" } %>
<%= f.label :taxon %>
- <%= f.text_field :taxon, data: { autocomplete_source: filter_taxon_path }, include_blank: true, class: 'form-control' %> + <%= f.collection_select :taxon, Taxon.order(:scientific_name), :id, :scientific_name, { include_blank: true }, { class:"form-control" } %>

diff --git a/app/views/marker_sequences/_form.html.erb b/app/views/marker_sequences/_form.html.erb index 98d6f3df..15cde75a 100644 --- a/app/views/marker_sequences/_form.html.erb +++ b/app/views/marker_sequences/_form.html.erb @@ -50,16 +50,16 @@
- <%= f.label :isolate_display_name, 'Isolate' %> + <%= f.label :isolate_id, 'Isolate' %> <% if @marker_sequence.isolate %> <%= link_to '', edit_isolate_path(@marker_sequence.isolate), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.text_field :isolate_display_name , data: { autocomplete_source: filter_isolates_path } , class: 'form-control'%> + <%= f.collection_select :isolate_id, Isolate.order(:display_name), :id, :display_name, { include_blank: true }, { class:"form-control" } %>
<%= f.label :marker %> - <%= f.collection_select(:marker_id, Marker.all, :id, :name, { :include_blank => '' }, { class: 'form-control' }) %> + <%= f.collection_select(:marker_id, Marker.all, :id, :name, {}, { class: 'form-control' }) %>
<%= render :partial => 'shared/associated_projects', :locals => { :form => f, :projects => associated_projects(@marker_sequence) } %> diff --git a/app/views/micronic_plates/_form.html.erb b/app/views/micronic_plates/_form.html.erb index 6f463a84..928f79ab 100644 --- a/app/views/micronic_plates/_form.html.erb +++ b/app/views/micronic_plates/_form.html.erb @@ -12,7 +12,7 @@
<%= f.label 'Rack' %> - <%= f.collection_select(:lab_rack_id, LabRack.all, :id, :rackcode, { :include_blank => '' }, { class: 'form-control' } ) %> + <%= f.collection_select(:lab_rack_id, LabRack.all, :id, :rackcode, { :include_blank => true }, { class: 'form-control' } ) %>
diff --git a/app/views/ngs_runs/_form.html.erb b/app/views/ngs_runs/_form.html.erb index 41a80cce..1b2fb7fc 100644 --- a/app/views/ngs_runs/_form.html.erb +++ b/app/views/ngs_runs/_form.html.erb @@ -37,8 +37,8 @@
- <%= f.label 'Associated Taxon' %> - <%= f.text_field :taxon_name, data: { autocomplete_source: filter_taxa_path }, class: 'form-control'%> + <%= f.label :taxon_id, 'Associated Taxon' %> + <%= f.collection_select :taxon_id, Taxon.order(:scientific_name), :id, :scientific_name, { include_blank: true }, { class:"form-control" } %>
diff --git a/app/views/orders/_form.html.erb b/app/views/orders/_form.html.erb deleted file mode 100644 index c47014d3..00000000 --- a/app/views/orders/_form.html.erb +++ /dev/null @@ -1,71 +0,0 @@ -<% provide(:title, @order.name) %> -<%= show_val_errors(@order)%> - -
- -
-

<%= @order.name%>

-
- - -
- <%= form_for(@order) do |f| %> - - - - -
- -
-
- -
- <%= f.label :name %> - <%= f.text_field :name, class: 'form-control' %> -
- -
- <%= f.label :author %> - <%= f.text_field :author, class: 'form-control' %> -
- -
- <%= f.label 'Belongs to' %> - <%= f.collection_select(:higher_order_taxon_id, HigherOrderTaxon.all, :id, :name, {}, { class: 'form-control' }) %> -
- - <%= render :partial => 'shared/associated_projects', :locals => { :form => f, :projects => associated_projects(@order) } %> -
- -
-
- - - - - - - - - - <% @order.families.order(:name).each do |c| %> - - - - <% end %> - - -
Name
- <%= link_to c.name,edit_family_path(c) %> -
-
-
- - <%= f.submit 'Update', :class => 'btn btn-default' %> - <% end %> -
-
- diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb deleted file mode 100644 index d1cef535..00000000 --- a/app/views/orders/edit.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<%= render 'form' %> - - - - - -
- <%= link_to '', 'javascript:history.go(-1)', :class => "glyphicon glyphicon-chevron-left" %> - - <%= link_to '', @order, method: :delete, data: { confirm: 'Are you sure?' }, :class => "glyphicon glyphicon-trash" %> -
\ No newline at end of file diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb deleted file mode 100644 index 00a4f7e4..00000000 --- a/app/views/orders/index.html.erb +++ /dev/null @@ -1,39 +0,0 @@ -
-
-

Orders

-
-
- - -
- - - - - - - - - - - - <% @orders.each do |order| %> - - - - - - - - <% end %> - -
NameHigher-order Taxon
<%= link_to order.name, edit_order_path(order) %> - <% if order.higher_order_taxon %> - <%= link_to order.higher_order_taxon.name, edit_higher_order_taxon_path(order.higher_order_taxon) %> - <% end %> - <%= link_to 'Delete', order, method: :delete, data: { confirm: 'Are you sure?' } %>
-
- -
- -<%= link_to 'New Order', new_order_path %> diff --git a/app/views/orders/index.json.jbuilder b/app/views/orders/index.json.jbuilder deleted file mode 100644 index 51345067..00000000 --- a/app/views/orders/index.json.jbuilder +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -json.array!(@orders) do |order| - json.extract! order, :id, :name, :author - json.url order_url(order, format: :json) -end diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb deleted file mode 100644 index dcc3d2bf..00000000 --- a/app/views/orders/new.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= render 'form' %> - -<%= link_to 'Back', orders_path %> diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb deleted file mode 100644 index c5e4ccb3..00000000 --- a/app/views/orders/show.html.erb +++ /dev/null @@ -1,18 +0,0 @@ - -

- Name: - <%= @order.name %> -

- -

- Author: - <%= @order.author %> -

- -

- Belongs to: - <%= @order.higher_order_taxon.name %> -

- -<%= link_to 'Edit', edit_order_path(@order) %> | -<%= link_to 'Back', orders_path %> diff --git a/app/views/orders/show.json.jbuilder b/app/views/orders/show.json.jbuilder deleted file mode 100644 index f182a27f..00000000 --- a/app/views/orders/show.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -json.extract! @order, :id, :name, :author, :created_at, :updated_at diff --git a/app/views/primer_reads/_form.html.erb b/app/views/primer_reads/_form.html.erb index 4064d90a..7af86ec1 100644 --- a/app/views/primer_reads/_form.html.erb +++ b/app/views/primer_reads/_form.html.erb @@ -39,11 +39,11 @@
- <%= f.label 'Contig' %> + <%= f.label :contig_id, 'Contig' %> <% if @primer_read.contig %> <%= link_to '', edit_contig_path(@primer_read.contig), :class => 'glyphicon glyphicon-share-alt', :title => "go to #{@primer_read.contig.name} " %> <% end %> - <%= f.text_field :contig_name , data: {autocomplete_source: filter_contigs_path} , class: 'form-control'%> + <%= f.collection_select :contig_id, Contig.order(:name), :id, :name, { include_blank: true }, { class:"form-control" } %>
diff --git a/app/views/primers/_form.html.erb b/app/views/primers/_form.html.erb index 43c8aa48..fbc68e10 100644 --- a/app/views/primers/_form.html.erb +++ b/app/views/primers/_form.html.erb @@ -18,7 +18,7 @@
<%= f.label 'Marker' %> - <%= f.collection_select(:marker_id, Marker.all, :id, :name, { include_blank: '' }, { class: 'form-control' }) %> + <%= f.collection_select(:marker_id, Marker.all, :id, :name, {}, { class: 'form-control' }) %>
diff --git a/app/views/progress_overview/index.html.erb b/app/views/progress_overview/index.html.erb index 853bdb7a..1276d037 100644 --- a/app/views/progress_overview/index.html.erb +++ b/app/views/progress_overview/index.html.erb @@ -25,13 +25,13 @@
@@ -45,7 +45,7 @@
-
+
diff --git a/app/views/projects/_form.html.erb b/app/views/projects/_form.html.erb index 75342848..c9faa7f3 100644 --- a/app/views/projects/_form.html.erb +++ b/app/views/projects/_form.html.erb @@ -26,7 +26,7 @@
<%= f.label :user_ids, 'Users' %>
- <%= f.collection_select(:user_ids, User.all, :id, :name, { include_blank: '' }, { multiple: true, class: 'form-control' }) %> + <%= f.collection_select(:user_ids, User.all, :id, :name, {}, { multiple: true, class: 'form-control' }) %>
diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb index 662a05c1..e72db430 100644 --- a/app/views/projects/index.html.erb +++ b/app/views/projects/index.html.erb @@ -46,13 +46,13 @@ <%= form_tag add_to_taxa_projects_path, :method => :get do %>

Select a taxon in order to associate it and all its descendants to the selected project:

- <%= label :project, 'Project' %>
- <%= collection_select :project, :id, user_projects, :id, :name, {}, { multiple: true } %> + <%= label :associated_project, 'Projects' %>
+ <%= collection_select :associated_project, :ids, user_projects, :id, :name, {}, { multiple: true } %>

<%= label :query, 'Taxon' %>
- <%= text_field_tag :associated_taxon, params[:associated_taxon], data: { autocomplete_source: filter_taxa_path } , class: 'form-control', style: 'display: inline;'%> + <%= collection_select :query, :associated_taxon, Taxon.order(:scientific_name), :id, :scientific_name, { include_blank: true }, { class:"form-control", style: 'display: inline;' } %>

<%= button_to 'Associate taxa', { type: 'Submit', method: 'get' }, { class: 'btn btn-default' } %> diff --git a/app/views/shared/_associated_projects.html.erb b/app/views/shared/_associated_projects.html.erb index 73528fc9..3a7b13ac 100644 --- a/app/views/shared/_associated_projects.html.erb +++ b/app/views/shared/_associated_projects.html.erb @@ -1,5 +1,5 @@
<%= form.label :project_ids, 'Projects this object belongs to' %>
- <%= form.collection_select :project_ids, projects.order(:name), :id, :name, {}, { multiple: true } %> + <%= form.collection_select :project_ids, projects.order(:name), :id, :name, {}, { class: 'form-control', multiple: true } %>
\ No newline at end of file diff --git a/app/views/species/_form.html.erb b/app/views/species/_form.html.erb deleted file mode 100644 index c72f89ca..00000000 --- a/app/views/species/_form.html.erb +++ /dev/null @@ -1,148 +0,0 @@ -<% provide(:title, @species.name_for_display) %> -<%= show_val_errors(@species)%> - -
- -
-

<%= @species.name_for_display %>

-
- -
- - <%= form_for(@species) do |f| %> - - <% a=[] %> - - <% unless @species.infraspecific? %> - <% str=@species.species_component %> - <% a = Species.where(:species_component => str)%> - <% end %> - - - - - - -
-
-
-
- <%= f.label 'Genus' %> - <%= f.text_field :genus_name, class: 'form-control' %> -
- -
- <%= f.label 'Species' %> - <%= f.text_field :species_epithet, class: 'form-control' %> -
- -
- <%= f.label :author, 'Author' %> - <%= f.text_field :author, class: 'form-control' %> -
- -
- <%= f.label 'Subspecies' %> - <%= f.text_field :infraspecific, class: 'form-control' %> -
- -
- <%= f.label :author_infra, 'Author (subsp.)' %> - <%= f.text_field :author_infra, class: 'form-control' %> -
- -
- <%= f.label 'Family' %> - <% if @species.family %> - <%= link_to '', edit_family_path(@species.family), :class => "glyphicon glyphicon-share-alt" %> - <% end %> - <%= f.text_field :family_name , data: {autocomplete_source: filter_families_path} , class: 'form-control'%> -
- -
- <%= f.label 'German name' %> - <%= f.text_field :german_name, class: 'form-control' %> -
- -
- <%= f.label 'Comment' %> - <%= f.text_area :comment, class: 'form-control' %> -
- - <%= render :partial => 'shared/associated_projects', :locals => { :form => f, :projects => associated_projects(@species) } %> - - <%= f.submit 'Update', :class => 'btn btn-default'%> -
- - <% if @species.id %> - <% if a.count > 1 %> -
-
-
- - - <% a.each do |subsp| %> - <% if subsp.infraspecific? %> - - <% end%> - <% end %> - -
<%= link_to subsp.name_for_display, edit_species_path(subsp) %>
-
- <% end %> -
-
-
- " class="table table-striped table-hover table-bordered"> - - - - - - - - - - - - - -
Specimen IDSpeciesHerbariumCollectorCollector's Field NumberLast updated
-
-
-
-
- <% url="https://www.google.com/search?q=#{@species.genus_name}+#{@species.species_epithet}" %> - -
- <% name_str=@species.species_component %> - <% name_str=name_str.gsub!(' ', '_') %> - <% url="https://de.m.wikipedia.org/wiki/#{name_str}" %> -
- width="800px" height="600px"> - -
-
- -
-
- <% end %> - - -
- - <% end %> - -
- -
diff --git a/app/views/species/edit.html.erb b/app/views/species/edit.html.erb deleted file mode 100644 index aac8c616..00000000 --- a/app/views/species/edit.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -<%= render 'form' %> - - - - - - -
- <%= link_to '', 'javascript:history.go(-1)', :class => "glyphicon glyphicon-chevron-left" %> - - <%= link_to '', @species, method: :delete, data: { confirm: 'Are you sure?' }, :class => "glyphicon glyphicon-trash" %> -
\ No newline at end of file diff --git a/app/views/species/index.html.erb b/app/views/species/index.html.erb deleted file mode 100644 index 8311cb4b..00000000 --- a/app/views/species/index.html.erb +++ /dev/null @@ -1,42 +0,0 @@ -
- -
-

Species

-
- -
- -
- " class="table table-striped table-hover table-bordered"> - - - - - - - - - - - - - - -
SpeciesAuthorFamilyLast Updated
-
-
- - <% if user_signed_in? %> -
- Import Taxa from Excel file <%= link_to '(Download example / template file)', 'https://s3-eu-west-1.amazonaws.com/gbol5/Species+upload+template.xls' %>: - <%= form_tag import_gbolii_species_index_path, multipart: true do %> - <%= file_field_tag :file %> -
- <%= submit_tag "Import", class: 'btn btn-default' %> - <% end %> -
- <% end %> - -
-
-<%= link_to ' New Species', new_species_path %> \ No newline at end of file diff --git a/app/views/species/index.json.jbuilder b/app/views/species/index.json.jbuilder deleted file mode 100644 index 6c362d17..00000000 --- a/app/views/species/index.json.jbuilder +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -json.array!(@species) do |species| - json.extract! species, :id, :author, :genus_name, :species_epithet - json.url species_url(species, format: :json) -end diff --git a/app/views/species/new.html.erb b/app/views/species/new.html.erb deleted file mode 100644 index c095a945..00000000 --- a/app/views/species/new.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= render 'form' %> - -<%= link_to 'Back', species_index_path %> diff --git a/app/views/species/show.html.erb b/app/views/species/show.html.erb deleted file mode 100644 index a826214e..00000000 --- a/app/views/species/show.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -

<%= notice %>

- -

- Author: - <%= @species.author %> -

- -

- Genus name: - <%= @species.genus_name %> -

- -

- Species epithet: - <%= @species.species_epithet %> -

- -<%= link_to 'Edit', edit_species_path(@species) %> | -<%= link_to 'Back', species_index_path %> diff --git a/app/views/species/show.json.jbuilder b/app/views/species/show.json.jbuilder deleted file mode 100644 index 3825e2ac..00000000 --- a/app/views/species/show.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -json.extract! @species, :id, :author, :genus_name, :species_epithet, :created_at, :updated_at diff --git a/app/views/taxa/_form.html.erb b/app/views/taxa/_form.html.erb index fc1b56d7..d45109e2 100644 --- a/app/views/taxa/_form.html.erb +++ b/app/views/taxa/_form.html.erb @@ -11,7 +11,10 @@ @@ -43,12 +46,13 @@ <% if @taxon.parent %> <%= link_to '', edit_taxon_path(@taxon.parent), :class => "glyphicon glyphicon-share-alt" %> <% end %> - <%= f.text_field :parent_name , data: { autocomplete_source: filter_taxa_path } , class: 'form-control'%> +
+ <%= f.collection_select :parent_id, Taxon.order(:taxonomic_rank), :id, :scientific_name, { include_blank: true }, { class:"form-control" } %>
- <%= f.label :taxonomic_rank %> - <%= f.select :taxonomic_rank, Taxon.taxonomic_ranks.keys.map { |r| [r.split('_')[1].capitalize, r] }, {}, { class: 'form-control' } %> + <%= f.label :taxonomic_rank %>
+ <%= f.select :taxonomic_rank, Taxon.taxonomic_ranks.keys.map { |r| [r.split('_')[1].capitalize, r] }, { include_blank: true }, { class:"form-control" } %>
@@ -71,7 +75,7 @@

Specimen directly associated with this Taxon:

- " class="table table-striped table-hover table-bordered"> +
" class="table table-striped table-hover table-bordered"> @@ -88,6 +92,27 @@
Specimen ID
+ +
+
+

Direct children of this taxon:

+
+ " class="table table-striped table-hover table-bordered"> + + + + + + + + + + + + +
Scientific nameSynonymCommon nameTaxonomic rankLast updated
+
+
<% end %>
<% end %> diff --git a/app/views/taxa/index.html.erb b/app/views/taxa/index.html.erb index cf93be82..44626690 100644 --- a/app/views/taxa/index.html.erb +++ b/app/views/taxa/index.html.erb @@ -11,45 +11,38 @@

- Select a root taxon to show a phylogenetic tree of all its descendants. + Select a root taxon to show a taxonomy of all its descendants. <%= select_tag('Root taxon', options_from_collection_for_select(Taxon.orphans.order(:taxonomic_rank).in_project(current_project_id), 'id', 'scientific_name'), - prompt: "Select a taxon", class: 'form-control root_select', id: 'taxonomy_root_select') %> + class: 'form-control root_select', id: 'taxonomy_root_select') %>

- +
+

+ Select a taxon to open and center it in the tree. + <%= collection_select :taxon, :search, Taxon.order(:scientific_name), :id, :scientific_name, { include_blank: true }, { class:"form-control" } %> +

+
- - -
- <%= text_field :taxon, :search, data: { autocomplete_source: filter_taxa_path } , class: 'form-control'%> - - - -
@@ -88,7 +81,7 @@

Please use this template: <%= link_to 'Taxon Import Template', "templates/taxon_upload_template.csv" %>

<%= form_tag import_csv_taxa_url, multipart: true do %> -

<%= file_field_tag :file %>

+

<%= file_field_tag :file, class: 'form-control' %>

<%= button_tag(class: 'btn btn-default') do %> <% end %> diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb index 71ebf6ca..4851a1a6 100644 --- a/app/views/users/_form.html.erb +++ b/app/views/users/_form.html.erb @@ -33,7 +33,7 @@
<%= f.label 'Responsibility' %>
- <%= f.collection_select :responsibility_ids, Responsibility.order(:name), :id, :name, { include_blank:'' }, { multiple:true, class: 'form-control' } %> + <%= f.collection_select :responsibility_ids, Responsibility.order(:name), :id, :name, {}, { multiple:true, class: 'form-control' } %>
diff --git a/config/deploy.rb b/config/deploy.rb index 3e4bf155..21298e74 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Change these -server '46.101.149.34', port: 1694, roles: %i[web app db], primary: true +server 'gbol5.de', port: 1694, roles: %i[web app db], primary: true set :repo_url, 'git@github.com:SarahW91/gbol5.git' set :application, 'gbol5' @@ -10,9 +10,6 @@ set :puma_threads, [1, 5] set :puma_workers, 2 -# Always deploy currently checked out branch -set :branch, Regexp.last_match(1) if `git branch` =~ /\* (\S+)\s/m - # Rbenv setup set :whenever_environment, fetch(:stage) set :whenever_identifier, "#{fetch(:application)}_#{fetch(:stage)}" @@ -21,6 +18,8 @@ "&rbenv_root=#{fetch :rbenv_path}'" end +set :rbenv_custom_path, "/home/sarah/.rbenv" + # Puma setup (Don't change these unless you know what you're doing) set :pty, false set :use_sudo, false @@ -30,8 +29,8 @@ set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock" set :puma_state, "#{shared_path}/tmp/pids/puma.state" set :puma_pid, "#{shared_path}/tmp/pids/puma.pid" -set :puma_access_log, "#{release_path}/log/puma.access.log" -set :puma_error_log, "#{release_path}/log/puma.error.log" +set :puma_access_log, "#{shared_path}/log/puma.access.log" +set :puma_error_log, "#{shared_path}/log/puma.error.log" set :puma_preload_app, true set :puma_worker_timeout, nil set :puma_init_active_record, true # Change to false when not using ActiveRecord @@ -40,8 +39,9 @@ set :ssh_options, port: 1694, forward_agent: true, user: fetch(:user), keys: %w[/home/sarah/.ssh/id_rsa] # Sidekiq setup -set sidekiq_log: File.join(release_path, 'log', 'sidekiq.log') +set sidekiq_log: File.join(shared_path, 'log', 'sidekiq.log') set sidekiq_config: File.join(shared_path, 'config', 'sidekiq.yml') +set :sidekiq_user => 'sarah' ## Defaults: # set :scm, :git diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 6cd4700a..d0212a69 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -12,13 +12,6 @@ # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) inflect.irregular 'taxon', 'taxa' - inflect.irregular 'syntaxon', 'syntaxa' - inflect.irregular 'OverviewFinishedTaxa', 'OverviewFinishedTaxa' - inflect.irregular 'OverviewAllTaxa', 'OverviewAllTaxa' - inflect.irregular 'overview_finished_taxa', 'overview_finished_taxa' - inflect.irregular 'overview_all_taxa', 'overview_all_taxa' - inflect.irregular 'HigherOrderTaxon', 'HigherOrderTaxa' - inflect.irregular 'higher_order_taxon', 'higher_order_taxa' inflect.irregular 'genus', 'genera' inflect.uncountable %w[species] inflect.uncountable %w[subspecies] diff --git a/config/routes.rb b/config/routes.rb index 6ed763f3..bc1384bc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -120,19 +120,10 @@ resources :issues - resources :higher_order_taxa do - collection do - get 'hierarchy_tree', defaults: { format: 'json' } - end - - member do - get 'show_species' - end - end - resources :taxa do member do get :show_individuals + get :show_children get :associated_specimen end @@ -146,22 +137,6 @@ end end - resources :species do - collection do - get :filter - get :get_mar - get :get_bry - get :get_ant - post :import_stuttgart - post :import_berlin - post :import_gbolii - end - - member do - get 'show_individuals' - end - end - resources :projects do collection do get :add_to_taxa @@ -182,8 +157,6 @@ end end - resources :orders - resources :tissues resources :primers do @@ -196,7 +169,11 @@ resources :micronic_plates - resources :markers + resources :markers do + collection do + get 'filter' + end + end resources :isolates do collection do @@ -222,15 +199,6 @@ end end - resources :families do - collection do - get 'filter' - end - member do - get 'show_species' - end - end - resources :responsibilities # HACK: avoid malicious users to directly type in the sign-up route diff --git a/db/migrate/20210510083108_remove_taxonomy_associations.rb b/db/migrate/20210510083108_remove_taxonomy_associations.rb new file mode 100644 index 00000000..d076cde8 --- /dev/null +++ b/db/migrate/20210510083108_remove_taxonomy_associations.rb @@ -0,0 +1,13 @@ +class RemoveTaxonomyAssociations < ActiveRecord::Migration[5.2] + def change + remove_column :individuals, :species_id + remove_column :ngs_runs, :higher_order_taxon_id + + drop_table :higher_order_taxa_markers + + drop_table :projects_species + drop_table :families_projects + drop_table :orders_projects + drop_table :higher_order_taxa_projects + end +end diff --git a/db/migrate/20210510084110_drop_taxonomic_tables.rb b/db/migrate/20210510084110_drop_taxonomic_tables.rb new file mode 100644 index 00000000..4ee3af58 --- /dev/null +++ b/db/migrate/20210510084110_drop_taxonomic_tables.rb @@ -0,0 +1,11 @@ +class DropTaxonomicTables < ActiveRecord::Migration[5.2] + def change + drop_table :divisions, force: :cascade + drop_table :families, force: :cascade + drop_table :higher_order_taxa, force: :cascade + drop_table :orders, force: :cascade + drop_table :species, force: :cascade + drop_table :subdivisions, force: :cascade + drop_table :taxonomic_classes, force: :cascade + end +end diff --git a/db/schema.rb b/db/schema.rb index a4eec461..a16df54c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -171,25 +171,6 @@ t.index ["priority", "run_at"], name: "delayed_jobs_priority" end - create_table "divisions", id: :serial, force: :cascade do |t| - t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - create_table "families", id: :serial, force: :cascade do |t| - t.string "name", limit: 255 - t.string "author", limit: 255 - t.datetime "created_at" - t.datetime "updated_at" - t.integer "order_id" - end - - create_table "families_projects", id: false, force: :cascade do |t| - t.integer "family_id" - t.integer "project_id" - end - create_table "freezers", id: :serial, force: :cascade do |t| t.string "freezercode", limit: 255 t.datetime "created_at" @@ -222,26 +203,6 @@ t.datetime "updated_at", null: false end - create_table "higher_order_taxa", id: :serial, force: :cascade do |t| - t.string "name", limit: 255 - t.datetime "created_at" - t.datetime "updated_at" - t.string "german_name", limit: 255 - t.integer "position" - t.string "ancestry" - t.index ["ancestry"], name: "index_higher_order_taxa_on_ancestry" - end - - create_table "higher_order_taxa_markers", id: false, force: :cascade do |t| - t.integer "higher_order_taxon_id" - t.integer "marker_id" - end - - create_table "higher_order_taxa_projects", id: false, force: :cascade do |t| - t.integer "higher_order_taxon_id" - t.integer "project_id" - end - create_table "homes", force: :cascade do |t| t.string "title" t.string "subtitle" @@ -278,7 +239,6 @@ t.datetime "updated_at" t.boolean "silica_gel" t.date "collected" - t.integer "species_id" t.string "herbarium_code", limit: 255 t.string "country", limit: 255 t.string "state_province", limit: 255 @@ -534,7 +494,6 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "comment" - t.integer "higher_order_taxon_id" t.string "set_tag_map_file_name" t.string "set_tag_map_content_type" t.integer "set_tag_map_file_size" @@ -554,7 +513,6 @@ t.boolean "analysis_requested", default: false t.boolean "analysis_started", default: false t.bigint "taxon_id" - t.index ["higher_order_taxon_id"], name: "index_ngs_runs_on_higher_order_taxon_id" t.index ["isolate_id"], name: "index_ngs_runs_on_isolate_id" t.index ["taxon_id"], name: "index_ngs_runs_on_taxon_id" end @@ -572,20 +530,6 @@ t.datetime "updated_at" end - create_table "orders", id: :serial, force: :cascade do |t| - t.string "name", limit: 255 - t.string "author", limit: 255 - t.datetime "created_at" - t.datetime "updated_at" - t.integer "higher_order_taxon_id" - t.integer "taxonomic_class_id" - end - - create_table "orders_projects", id: false, force: :cascade do |t| - t.integer "order_id" - t.integer "project_id" - end - create_table "partial_cons", id: :serial, force: :cascade do |t| t.text "sequence" t.text "aligned_sequence" @@ -700,11 +644,6 @@ t.index ["project_id", "shelf_id"], name: "index_projects_shelves_on_project_id_and_shelf_id" end - create_table "projects_species", id: false, force: :cascade do |t| - t.integer "project_id" - t.integer "species_id" - end - create_table "projects_tag_primer_maps", id: false, force: :cascade do |t| t.integer "project_id", null: false t.integer "tag_primer_map_id", null: false @@ -743,32 +682,6 @@ t.index ["freezer_id"], name: "index_shelves_on_freezer_id" end - create_table "species", id: :serial, force: :cascade do |t| - t.string "author", limit: 255 - t.string "genus_name", limit: 255 - t.string "species_epithet", limit: 255 - t.datetime "created_at" - t.datetime "updated_at" - t.integer "family_id" - t.string "infraspecific", limit: 255 - t.text "comment" - t.string "german_name", limit: 255 - t.string "author_infra", limit: 255 - t.string "synonym", limit: 255 - t.string "composed_name", limit: 255 - t.string "species_component" - end - - create_table "subdivisions", id: :serial, force: :cascade do |t| - t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "position" - t.string "german_name" - t.integer "division_id" - t.index ["division_id"], name: "index_subdivisions_on_division_id" - end - create_table "tag_primer_maps", id: :serial, force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -799,14 +712,6 @@ t.index ["ancestry"], name: "index_taxa_on_ancestry" end - create_table "taxonomic_classes", id: :serial, force: :cascade do |t| - t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "subdivision_id" - t.string "german_name" - end - create_table "tissues", id: :serial, force: :cascade do |t| t.string "name", limit: 255 t.datetime "created_at" @@ -856,9 +761,7 @@ add_foreign_key "marker_sequence_searches", "projects" add_foreign_key "mislabel_analyses", "markers" add_foreign_key "mislabels", "marker_sequences" - add_foreign_key "ngs_runs", "higher_order_taxa" add_foreign_key "ngs_runs", "taxa" add_foreign_key "plant_plates", "lab_racks" add_foreign_key "shelves", "freezers" - add_foreign_key "subdivisions", "divisions" end diff --git a/db/views/overview_all_taxa_matviews_v01.sql b/db/views/overview_all_taxa_matviews_v01.sql deleted file mode 100644 index 6f5bc5e4..00000000 --- a/db/views/overview_all_taxa_matviews_v01.sql +++ /dev/null @@ -1,30 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - o.name AS order, - hot.name AS higher_order_taxon -FROM - ((families f -INNER JOIN orders o ON f.order_id = o.id) -INNER JOIN higher_order_taxa hot ON o.higher_order_taxon_id = hot.id) \ No newline at end of file diff --git a/db/views/overview_all_taxa_matviews_v02.sql b/db/views/overview_all_taxa_matviews_v02.sql deleted file mode 100644 index 2c95f9b4..00000000 --- a/db/views/overview_all_taxa_matviews_v02.sql +++ /dev/null @@ -1,34 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - o.name AS tax_order, - hot.name AS higher_order_taxon, - f.*, - COUNT(sp.family_id) AS species_cnt -FROM ((families f - INNER JOIN orders o ON f.order_id = o.id) - INNER JOIN higher_order_taxa hot ON o.higher_order_taxon_id = hot.id) - LEFT OUTER JOIN species sp - ON f.id = sp.family_id - GROUP BY f.id, f.name, o.name, hot.name diff --git a/db/views/overview_all_taxa_matviews_v03.sql b/db/views/overview_all_taxa_matviews_v03.sql deleted file mode 100644 index 1314f626..00000000 --- a/db/views/overview_all_taxa_matviews_v03.sql +++ /dev/null @@ -1,29 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - f.*, - COUNT(sp.family_id) AS species_cnt -FROM families f - LEFT OUTER JOIN species sp ON f.id = sp.family_id - GROUP BY f.id, f.name \ No newline at end of file diff --git a/db/views/overview_all_taxa_matviews_v04.sql b/db/views/overview_all_taxa_matviews_v04.sql deleted file mode 100644 index 4c4f68c4..00000000 --- a/db/views/overview_all_taxa_matviews_v04.sql +++ /dev/null @@ -1,46 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - COUNT(sp.family_id) AS species_cnt -FROM families f - LEFT OUTER JOIN species sp ON f.id = sp.family_id - GROUP BY f.id, f.name - --- Family.joins(:species).select('family.name AS family_name').group(:name).order(:name).count(:species) --- SELECT --- COUNT(species) AS count_species, --- "families"."name" AS families_name --- FROM "families" --- INNER JOIN "species" ON "species"."family_id" = "families"."id" --- GROUP BY "families"."name" --- ORDER BY "families"."name" ASC - --- Species.joins(:family).order('families.name').group('families.name').count --- SELECT --- COUNT(*) AS count_all, --- families.name AS families_name --- FROM "species" --- INNER JOIN "families" ON "families"."id" = "species"."family_id" --- GROUP BY families.name --- ORDER BY families.name \ No newline at end of file diff --git a/db/views/overview_finished_taxa_matviews_v01.sql b/db/views/overview_finished_taxa_matviews_v01.sql deleted file mode 100644 index 825c225a..00000000 --- a/db/views/overview_finished_taxa_matviews_v01.sql +++ /dev/null @@ -1,35 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - COUNT(spe.family_id) AS all_species_cnt, - COUNT(CASE WHEN mseq.marker_ID = 4 THEN 1 END) AS trnLF_cnt, - COUNT(CASE WHEN mseq.marker_ID = 5 THEN 1 END) AS ITS_cnt, - COUNT(CASE WHEN mseq.marker_ID = 6 THEN 1 END) AS rpl16_cnt, - COUNT(CASE WHEN mseq.marker_ID = 7 THEN 1 END) AS trnK_matK_cnt -FROM ((((families f - LEFT OUTER JOIN species spe ON f.id = spe.family_id) - LEFT OUTER JOIN individuals ind ON spe.id = ind.species_id) - LEFT OUTER JOIN isolates iso ON ind.id = iso.individual_id) - LEFT OUTER JOIN marker_sequences mseq ON iso.id = mseq.isolate_id) -GROUP BY f.id, f.name \ No newline at end of file diff --git a/db/views/overview_finished_taxa_matviews_v02.sql b/db/views/overview_finished_taxa_matviews_v02.sql deleted file mode 100644 index 29009a78..00000000 --- a/db/views/overview_finished_taxa_matviews_v02.sql +++ /dev/null @@ -1,35 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - COUNT(CASE WHEN spe.family_id = f.id THEN 1 END) AS species_cnt, - COUNT(CASE WHEN mseq.marker_ID = 4 THEN 1 END) AS trnLF_cnt, - COUNT(CASE WHEN mseq.marker_ID = 5 THEN 1 END) AS ITS_cnt, - COUNT(CASE WHEN mseq.marker_ID = 6 THEN 1 END) AS rpl16_cnt, - COUNT(CASE WHEN mseq.marker_ID = 7 THEN 1 END) AS trnK_matK_cnt -FROM ((((families f - LEFT OUTER JOIN species spe ON f.id = spe.family_id) - LEFT OUTER JOIN individuals ind ON spe.id = ind.species_id) - LEFT OUTER JOIN isolates iso ON ind.id = iso.individual_id) - LEFT OUTER JOIN marker_sequences mseq ON iso.id = mseq.isolate_id) -GROUP BY f.id, f.name \ No newline at end of file diff --git a/db/views/overview_finished_taxa_matviews_v03.sql b/db/views/overview_finished_taxa_matviews_v03.sql deleted file mode 100644 index 29009a78..00000000 --- a/db/views/overview_finished_taxa_matviews_v03.sql +++ /dev/null @@ -1,35 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - COUNT(CASE WHEN spe.family_id = f.id THEN 1 END) AS species_cnt, - COUNT(CASE WHEN mseq.marker_ID = 4 THEN 1 END) AS trnLF_cnt, - COUNT(CASE WHEN mseq.marker_ID = 5 THEN 1 END) AS ITS_cnt, - COUNT(CASE WHEN mseq.marker_ID = 6 THEN 1 END) AS rpl16_cnt, - COUNT(CASE WHEN mseq.marker_ID = 7 THEN 1 END) AS trnK_matK_cnt -FROM ((((families f - LEFT OUTER JOIN species spe ON f.id = spe.family_id) - LEFT OUTER JOIN individuals ind ON spe.id = ind.species_id) - LEFT OUTER JOIN isolates iso ON ind.id = iso.individual_id) - LEFT OUTER JOIN marker_sequences mseq ON iso.id = mseq.isolate_id) -GROUP BY f.id, f.name \ No newline at end of file diff --git a/db/views/overview_finished_taxa_matviews_v04.sql b/db/views/overview_finished_taxa_matviews_v04.sql deleted file mode 100644 index e91b6100..00000000 --- a/db/views/overview_finished_taxa_matviews_v04.sql +++ /dev/null @@ -1,35 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - COUNT(spe.family_id) AS species_cnt, - COUNT(CASE WHEN mseq.marker_ID = 4 THEN 1 END) AS trnLF_cnt, - COUNT(CASE WHEN mseq.marker_ID = 5 THEN 1 END) AS ITS_cnt, - COUNT(CASE WHEN mseq.marker_ID = 6 THEN 1 END) AS rpl16_cnt, - COUNT(CASE WHEN mseq.marker_ID = 7 THEN 1 END) AS trnK_matK_cnt -FROM ((((families f - LEFT OUTER JOIN species spe ON f.id = spe.family_id) - LEFT OUTER JOIN individuals ind ON spe.id = ind.species_id) - LEFT OUTER JOIN isolates iso ON ind.id = iso.individual_id) - LEFT OUTER JOIN marker_sequences mseq ON iso.id = mseq.isolate_id) -GROUP BY f.id, f.name \ No newline at end of file diff --git a/db/views/overview_finished_taxa_matviews_v05.sql b/db/views/overview_finished_taxa_matviews_v05.sql deleted file mode 100644 index e91b6100..00000000 --- a/db/views/overview_finished_taxa_matviews_v05.sql +++ /dev/null @@ -1,35 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - f.name AS family, - COUNT(spe.family_id) AS species_cnt, - COUNT(CASE WHEN mseq.marker_ID = 4 THEN 1 END) AS trnLF_cnt, - COUNT(CASE WHEN mseq.marker_ID = 5 THEN 1 END) AS ITS_cnt, - COUNT(CASE WHEN mseq.marker_ID = 6 THEN 1 END) AS rpl16_cnt, - COUNT(CASE WHEN mseq.marker_ID = 7 THEN 1 END) AS trnK_matK_cnt -FROM ((((families f - LEFT OUTER JOIN species spe ON f.id = spe.family_id) - LEFT OUTER JOIN individuals ind ON spe.id = ind.species_id) - LEFT OUTER JOIN isolates iso ON ind.id = iso.individual_id) - LEFT OUTER JOIN marker_sequences mseq ON iso.id = mseq.isolate_id) -GROUP BY f.id, f.name \ No newline at end of file diff --git a/db/views/overview_finished_taxa_matviews_v06.sql b/db/views/overview_finished_taxa_matviews_v06.sql deleted file mode 100644 index 92ecfe85..00000000 --- a/db/views/overview_finished_taxa_matviews_v06.sql +++ /dev/null @@ -1,37 +0,0 @@ --- --- Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA --- barcode data and metadata. --- Copyright (C) 2020 Kai Müller , Sarah Wiechers --- --- --- This file is part of Barcode Workflow Manager. --- --- Barcode Workflow Manager is free software: you can redistribute it and/or modify --- it under the terms of the GNU Affero General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- Barcode Workflow Manager is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU Affero General Public License for more details. --- --- You should have received a copy of the GNU Affero General Public License --- along with Barcode Workflow Manager. If not, see --- . --- -SELECT - COUNT(CASE WHEN "marker_sequences"."marker_id" = 4 THEN 1 END) AS trnLF_cnt, - COUNT(CASE WHEN "marker_sequences"."marker_id" = 5 THEN 1 END) AS ITS_cnt, - COUNT(CASE WHEN "marker_sequences"."marker_id" = 6 THEN 1 END) AS rpl16_cnt, - COUNT(CASE WHEN "marker_sequences"."marker_id" = 7 THEN 1 END) AS trnK_matK_cnt, - families.name AS families_name -FROM "marker_sequences" - INNER JOIN "isolates" ON "isolates"."id" = "marker_sequences"."isolate_id" - INNER JOIN "individuals" ON "individuals"."id" = "isolates"."individual_id" - INNER JOIN "species" ON "species"."id" = "individuals"."species_id" - INNER JOIN "families" ON "families"."id" = "species"."family_id" -GROUP BY families.name -ORDER BY families.name - --- MarkerSequence.joins(isolate: [individual: [species: :family]]).where(:marker => 5).order('families.name').group('families.name').count \ No newline at end of file diff --git a/spec/controllers/taxa_controller_spec.rb b/spec/controllers/taxa_controller_spec.rb deleted file mode 100644 index 0bd7245b..00000000 --- a/spec/controllers/taxa_controller_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe TaxaController, type: :controller do - -end diff --git a/spec/factories/contig_searches.rb b/spec/factories/contig_searches.rb index 6efdf1b2..3537cc72 100644 --- a/spec/factories/contig_searches.rb +++ b/spec/factories/contig_searches.rb @@ -26,7 +26,6 @@ FactoryBot.define do factory :contig_search do |cs| cs.assembled { ["assembled", "unassembled", "both"].sample } - cs.family { Faker::Lorem.word } cs.has_warnings { ContigSearch.has_warnings.keys.sample } cs.marker { Faker::Lorem.word } cs.max_age { Faker::Time.backward(days: 176) } @@ -34,8 +33,7 @@ cs.min_age { Faker::Time.backward(days: 1) } cs.min_update { Faker::Time.backward(days: 1) } cs.name { Faker::Lorem.word } - cs.order { Faker::Lorem.word } - cs.species { Faker::Lorem.word } + cs.taxon { Faker::Lorem.word } cs.specimen { Faker::Lorem.word } cs.title { Faker::Lorem.word } cs.verified { ["verified", "unverified", "both"].sample } diff --git a/spec/factories/divisions.rb b/spec/factories/divisions.rb deleted file mode 100644 index 2134b0df..00000000 --- a/spec/factories/divisions.rb +++ /dev/null @@ -1,29 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'faker' - -FactoryBot.define do - factory :division do |d| - d.name { Faker::Lorem.word } - end -end diff --git a/spec/factories/families.rb b/spec/factories/families.rb deleted file mode 100644 index 4a47cdaa..00000000 --- a/spec/factories/families.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'faker' - -FactoryBot.define do - factory :family do |f| - f.author { Faker::Science.scientist } - f.name { Faker::Food.vegetables } - - factory :family_with_taxonomy do - association :order, factory: :order_with_taxonomy - end - end -end \ No newline at end of file diff --git a/spec/factories/higher_order_taxa.rb b/spec/factories/higher_order_taxa.rb deleted file mode 100644 index 19ad7228..00000000 --- a/spec/factories/higher_order_taxa.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'faker' - -FactoryBot.define do - factory :higher_order_taxon do |hot| - hot.german_name { Faker::Lorem.word } - hot.name { Faker::Lorem.word } - hot.position { Faker::Number.digit } - end -end diff --git a/spec/factories/individual_searches.rb b/spec/factories/individual_searches.rb index c189cd73..ad264aa3 100644 --- a/spec/factories/individual_searches.rb +++ b/spec/factories/individual_searches.rb @@ -25,13 +25,11 @@ FactoryBot.define do factory :individual_search do |is| is.DNA_bank_id { Faker::Lorem.word } - is.family { Faker::Lorem.word } is.has_issue { Faker::Number.between(from: 0, to: 2) } is.has_problematic_location { Faker::Number.between(from: 0, to: 2) } - is.has_species { Faker::Number.between(from: 0, to: 2) } + is.has_taxon { Faker::Number.between(from: 0, to: 2) } is.herbarium { Faker::Lorem.word } - is.order { Faker::Lorem.word } - is.species { Faker::Lorem.word } + is.taxon { Faker::Lorem.word } is.title { Faker::Lorem.word } end end \ No newline at end of file diff --git a/spec/factories/marker_sequence_searches.rb b/spec/factories/marker_sequence_searches.rb index 263c9ce3..88b6c10e 100644 --- a/spec/factories/marker_sequence_searches.rb +++ b/spec/factories/marker_sequence_searches.rb @@ -24,10 +24,8 @@ FactoryBot.define do factory :marker_sequence_search do |ms| - ms.family { Faker::Lorem.word } - ms.has_species { Faker::Boolean.boolean } + ms.has_taxon { Faker::Boolean.boolean } ms.has_warnings { Faker::Number.between(from: 0, to: 2) } - ms.higher_order_taxon { Faker::Lorem.word } ms.marker { Faker::Lorem.word } ms.max_age { Faker::Time.backward(days: 176) } ms.max_length { Faker::Number.between(from: 2500, to: 5000) } @@ -36,9 +34,8 @@ ms.min_length { Faker::Number.between(from: 0, to: 2500) } ms.min_update { Faker::Time.backward(days: 1) } ms.name { Faker::Lorem.word } - ms.no_isolate { Faker::Boolean.boolean } - ms.order { Faker::Lorem.word } - ms.species { Faker::Lorem.word } + ms.no_isolate { Faker::Boolean.boolean } + ms.taxon { Faker::Lorem.word } ms.specimen { Faker::Lorem.word } ms.title { Faker::GreekPhilosophers.name } ms.verified { ["verified", "unverified", "both"].sample } diff --git a/spec/factories/orders.rb b/spec/factories/orders.rb deleted file mode 100644 index 29f098e5..00000000 --- a/spec/factories/orders.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'faker' - -FactoryBot.define do - factory :order do |o| - o.author { Faker::Science.scientist } - o.name { Faker::Food.vegetables } - - factory :order_with_taxonomy do - association :higher_order_taxon, factory: :higher_order_taxon - end - end -end \ No newline at end of file diff --git a/spec/factories/species.rb b/spec/factories/species.rb deleted file mode 100644 index fc67cf6d..00000000 --- a/spec/factories/species.rb +++ /dev/null @@ -1,51 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'faker' - -FactoryBot.define do - factory :species do |s| - s.author { Faker::Name.name_with_middle } - s.author_infra { Faker::Name.name_with_middle } - s.comment { Faker::Lorem.paragraph } - s.genus_name { Faker::Space.planet } - s.german_name { Faker::Lorem.word } - s.infraspecific { Faker::Lorem.word } - s.species_component { Faker::Lorem.word } - s.species_epithet { Faker::Lorem.word } - s.synonym { Faker::Lorem.word } - - factory :species_with_taxonomy do - association :family, factory: :family_with_taxonomy - end - - factory :species_with_individuals do - transient do - individual_count { 10 } - end - - after(:create) do |species, evaluator| - create_list(:individual, evaluator.individual_count, species: species) - end - end - end -end \ No newline at end of file diff --git a/spec/factories/subdividions.rb b/spec/factories/subdividions.rb deleted file mode 100644 index f2ccc820..00000000 --- a/spec/factories/subdividions.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'faker' - -FactoryBot.define do - factory :subdivision do |s| - s.german_name { Faker::Lorem.word } - s.name { Faker::Lorem.word } - s.position { Faker::Number.digit } - end -end diff --git a/spec/factories/taxonomic_classes.rb b/spec/factories/taxonomic_classes.rb deleted file mode 100644 index 1a3eec56..00000000 --- a/spec/factories/taxonomic_classes.rb +++ /dev/null @@ -1,30 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'faker' - -FactoryBot.define do - factory :taxonomic_class do |t| - t.german_name { Faker::Lorem.word } - t.name { Faker::Lorem.word } - end -end diff --git a/spec/features/advanced_searches_spec.rb b/spec/features/advanced_searches_spec.rb index d58c71ec..6f33905e 100644 --- a/spec/features/advanced_searches_spec.rb +++ b/spec/features/advanced_searches_spec.rb @@ -92,12 +92,10 @@ def can_create - order = FactoryBot.create(:order) - family = FactoryBot.create(:family, order: order) - species1 = FactoryBot.create(:species, family: family, genus_name: "Luzula", species_epithet: "rubella") - species2 = FactoryBot.create(:species, family: family, genus_name: "Rosa", species_epithet: "arvensis") - individual1 = FactoryBot.create(:individual, species: species1) - individual2 = FactoryBot.create(:individual, species: species2) + taxon1 = FactoryBot.create(:taxon, scientific_name: "Luzula rubella") + taxon2 = FactoryBot.create(:taxon, scientific_name: "Rosa arvensis") + individual1 = FactoryBot.create(:individual, taxon: taxon1) + individual2 = FactoryBot.create(:individual, taxon: taxon2) isolate1 = FactoryBot.create(:isolate, individual: individual1) isolate2 = FactoryBot.create(:isolate, individual: individual2) @@ -110,7 +108,7 @@ def can_create expect(current_path).to eql(new_marker_sequence_search_path) - fill_in 'Species', :with => species1.composed_name + fill_in 'Taxon', :with => taxon1.scientific_name expect(page).to have_button "Search" click_on 'Search' diff --git a/spec/features/overview_diagrams_spec.rb b/spec/features/overview_diagrams_spec.rb index d4b7f39e..48259c2d 100644 --- a/spec/features/overview_diagrams_spec.rb +++ b/spec/features/overview_diagrams_spec.rb @@ -24,77 +24,77 @@ RSpec.feature "Advanced marker sequence searches", type: :feature, js: true do before(:each) { @general_project = Project.find_or_create_by(name: 'All') } - - context "view diagrams" do - scenario "Visitor can view overview diagrams" do - can_view_diagrams - end - - scenario "Guest can view overview diagrams" do - user = create(:user, role: 'guest', default_project_id: @general_project.id) - sign_in user - - can_view_diagrams - end - - scenario "User can view overview diagrams" do - user = create(:user, role: 'user', default_project_id: @general_project.id) - sign_in user - - can_view_diagrams - end - - scenario "Supervisor can view overview diagrams" do - user = create(:user, role: 'supervisor', default_project_id: @general_project.id) - sign_in user - - can_view_diagrams - end - - scenario "Admin can view overview diagrams" do - user = create(:user, role: 'admin', default_project_id: @general_project.id) - sign_in user - - can_view_diagrams - end - end - - def can_view_diagrams - 10.times { FactoryBot.create(:marker_sequence_with_taxonomy) } - - visit overview_diagram_index_path - expect(current_path).to eql(overview_diagram_index_path) - - expect(page).to have_link "View overview tables" - - # All species - expect(page).to have_content "Number of species per taxon" - expect(page).to have_selector(:id, 'all_species', class: 'overview_diagram') - expect(page).to have_selector(:id, 'sequence1', class: 'sequence') - expect(page).to have_selector(:id, 'chart1', class: 'chart') - - chart1 = page.find(:id, 'chart1', class: 'chart') - within chart1 do - expect(page).to have_css('svg') - expect(page).to have_css('path') - expect(page).to have_selector('#explanation1', class: 'explanation', visible: false) - find('path', match: :first).hover - expect(page).to have_selector('#explanation1', class: 'explanation', visible: true) - end - - # Marker specific - expect(page).to have_content "Number of barcode sequences" - expect(page).to have_selector(:id, 'sequence2', class: 'sequence') - expect(page).to have_selector(:id, 'chart2', class: 'chart') - - chart2 = page.find(:id, 'chart2', class: 'chart') - within chart2 do - expect(page).to have_css('svg') - expect(page).to have_css('path') - expect(page).to have_selector('#explanation2', class: 'explanation', visible: false) - end - - Capybara.reset_sessions! - DatabaseCleaner.clean - end + # + # context "view diagrams" do + # scenario "Visitor can view overview diagrams" do + # can_view_diagrams + # end + # + # scenario "Guest can view overview diagrams" do + # user = create(:user, role: 'guest', default_project_id: @general_project.id) + # sign_in user + # + # can_view_diagrams + # end + # + # scenario "User can view overview diagrams" do + # user = create(:user, role: 'user', default_project_id: @general_project.id) + # sign_in user + # + # can_view_diagrams + # end + # + # scenario "Supervisor can view overview diagrams" do + # user = create(:user, role: 'supervisor', default_project_id: @general_project.id) + # sign_in user + # + # can_view_diagrams + # end + # + # scenario "Admin can view overview diagrams" do + # user = create(:user, role: 'admin', default_project_id: @general_project.id) + # sign_in user + # + # can_view_diagrams + # end + # end + # + # def can_view_diagrams + # 10.times { FactoryBot.create(:marker_sequence_with_taxonomy) } + # + # visit overview_diagram_index_path + # expect(current_path).to eql(overview_diagram_index_path) + # + # expect(page).to have_link "View overview tables" + # + # # All species + # expect(page).to have_content "Number of species per taxon" + # expect(page).to have_selector(:id, 'all_species', class: 'overview_diagram') + # expect(page).to have_selector(:id, 'sequence1', class: 'sequence') + # expect(page).to have_selector(:id, 'chart1', class: 'chart') + # + # chart1 = page.find(:id, 'chart1', class: 'chart') + # within chart1 do + # expect(page).to have_css('svg') + # expect(page).to have_css('path') + # expect(page).to have_selector('#explanation1', class: 'explanation', visible: false) + # find('path', match: :first).hover + # expect(page).to have_selector('#explanation1', class: 'explanation', visible: true) + # end + # + # # Marker specific + # expect(page).to have_content "Number of barcode sequences" + # expect(page).to have_selector(:id, 'sequence2', class: 'sequence') + # expect(page).to have_selector(:id, 'chart2', class: 'chart') + # + # chart2 = page.find(:id, 'chart2', class: 'chart') + # within chart2 do + # expect(page).to have_css('svg') + # expect(page).to have_css('path') + # expect(page).to have_selector('#explanation2', class: 'explanation', visible: false) + # end + # + # Capybara.reset_sessions! + # DatabaseCleaner.clean + # end end diff --git a/spec/models/division_spec.rb b/spec/models/division_spec.rb deleted file mode 100644 index f7c7ebf6..00000000 --- a/spec/models/division_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'rails_helper' - -RSpec.describe Division do - subject { FactoryBot.create(:division) } - - it "is valid with valid attributes" do - should be_valid - end - - it "has many subdivisions" do - should have_many(:subdivisions) - end -end \ No newline at end of file diff --git a/spec/models/family_spec.rb b/spec/models/family_spec.rb deleted file mode 100644 index c2b7a9ca..00000000 --- a/spec/models/family_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'rails_helper' -require Rails.root.join "spec/concerns/project_record_spec.rb" - -RSpec.describe Family do - before(:all) { Project.create(name: 'All') } - it_behaves_like "project_record" - - subject { FactoryBot.create(:family) } - - it "is valid with valid attributes" do - should be_valid - end - - it "is not valid without a name" do - should validate_presence_of(:name) - end - - it "has one order" do - should belong_to(:order) - end - - it "has many species" do - should have_many(:species) - end - - context "returns number of families in higher order taxon" do - before(:each) { @hot = FactoryBot.create(:higher_order_taxon) } - - it "returns correct number of families in higher order taxon" do - order = FactoryBot.create(:order, higher_order_taxon: @hot) - - FactoryBot.create(:family, order: order) - FactoryBot.create(:family, order: order) - FactoryBot.create(:family, order: order) - - expect(Family.in_higher_order_taxon(@hot.id)).to be == 3 - end - - it "returns correct number for no orders in higher order taxon" do - expect(Family.in_higher_order_taxon(@hot.id)).to be == 0 - end - end -end \ No newline at end of file diff --git a/spec/models/higher_order_taxon_spec.rb b/spec/models/higher_order_taxon_spec.rb deleted file mode 100644 index d3e71f03..00000000 --- a/spec/models/higher_order_taxon_spec.rb +++ /dev/null @@ -1,55 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'rails_helper' -require Rails.root.join 'spec/concerns/project_record_spec.rb' - -RSpec.describe HigherOrderTaxon do - before(:all) { Project.create(name: 'All') } - it_behaves_like "project_record" - - subject { FactoryBot.create(:higher_order_taxon) } - - it "is valid with valid attributes" do - should be_valid - end - - it "is not valid without a name" do - should validate_presence_of(:name) - end - - it "has and belongs to many markers" do - should have_and_belong_to_many(:markers) - end - - it "has many orders" do - should have_many(:orders) - end - - it "has many families" do - should have_many(:families).through(:orders) - end - - it "has many NGS runs" do - should have_many(:ngs_runs) - end -end \ No newline at end of file diff --git a/spec/models/individual_spec.rb b/spec/models/individual_spec.rb index 86c3f736..82c0e133 100644 --- a/spec/models/individual_spec.rb +++ b/spec/models/individual_spec.rb @@ -33,8 +33,8 @@ should be_valid end - it "belongs to a species" do - should belong_to(:species) + it "belongs to a taxon" do + should belong_to(:taxon) end it "belongs to a herbarium" do @@ -61,48 +61,48 @@ xit "assigns DNA bank info" do; end - context "returns associated species name" do - it "returns name of associated species if one exists" do - species = FactoryBot.create(:species) - individual = FactoryBot.create(:individual, species: species) + context "returns associated taxon name" do + it "returns name of associated taxon if one exists" do + taxon = FactoryBot.create(:taxon) + individual = FactoryBot.create(:individual, taxon: taxon) - expect(individual.species_name).to be == species.composed_name + expect(individual.taxon_name).to be == taxon.scientific_name end - it "returns nil if no associated species exists" do - individual = FactoryBot.create(:individual, species: nil) - expect(individual.species_name).to be == nil + it "returns nil if no associated taxon exists" do + individual = FactoryBot.create(:individual, taxon: nil) + expect(individual.taxon_name).to be == nil end end - context "changes associated species name" do - it "changes name of associated species if one exists" do - species1 = FactoryBot.create(:species) - species2 = FactoryBot.create(:species) + context "changes associated taxon name" do + it "changes name of associated taxon if one exists" do + taxon1 = FactoryBot.create(:taxon) + taxon2 = FactoryBot.create(:taxon) - individual = FactoryBot.create(:individual, species: species1) + individual = FactoryBot.create(:individual, taxon: taxon1) - expect { individual.species_name = species2.composed_name }.to change { individual.species }.to species2 + expect { individual.taxon_name = taxon2.scientific_name }.to change { individual.taxon }.to taxon2 end - it "creates new associated species if none exists" do - species_name = Faker::Lorem.word + it "creates new associated taxon if none exists" do + taxon_name = Faker::Lorem.word - expect { subject.species_name = species_name }.to change { Species.count }.by 1 + expect { subject.taxon_name = taxon_name }.to change { Taxon.count }.by 1 end - it "does not change associated species if nil is provided" do - species = FactoryBot.create(:species) - individual = FactoryBot.create(:individual, species: species) + it "does not change associated taxon if nil is provided" do + taxon = FactoryBot.create(:taxon) + individual = FactoryBot.create(:individual, taxon: taxon) - expect { individual.species_name = nil }.not_to change { individual.species } + expect { individual.taxon_name = nil }.not_to change { individual.taxon } end - it "removes associated species if an empty string is provided" do - species = FactoryBot.create(:species) - individual = FactoryBot.create(:individual, species: species) + it "removes associated taxon if an empty string is provided" do + taxon = FactoryBot.create(:taxon) + individual = FactoryBot.create(:individual, taxon: taxon) - expect { individual.species_name = '' }.to change { individual.species }.to nil + expect { individual.taxon_name = '' }.to change { individual.taxon }.to nil end end diff --git a/spec/models/marker_spec.rb b/spec/models/marker_spec.rb index 3a96a9fc..a5e0c39a 100644 --- a/spec/models/marker_spec.rb +++ b/spec/models/marker_spec.rb @@ -37,8 +37,8 @@ should validate_presence_of(:name) end - it "has and belongs to many higher order taxa" do - should have_and_belong_to_many(:higher_order_taxa) + it "has and belongs to many taxa" do + should have_and_belong_to_many(:taxa) end it "have many marker sequences" do diff --git a/spec/models/ngs_run_spec.rb b/spec/models/ngs_run_spec.rb index 63c5ed47..21b406d7 100644 --- a/spec/models/ngs_run_spec.rb +++ b/spec/models/ngs_run_spec.rb @@ -41,8 +41,8 @@ should validate_uniqueness_of(:name) end - it "belongs to a higher order taxon" do - should belong_to(:higher_order_taxon) + it "belongs to a taxon" do + should belong_to(:taxon) end it "has many tag primer maps" do diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb deleted file mode 100644 index 1de195ff..00000000 --- a/spec/models/order_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'rails_helper' -require Rails.root.join "spec/concerns/project_record_spec.rb" - -RSpec.describe Order do - before(:all) { Project.create(name: 'All') } - it_behaves_like "project_record" - - subject { FactoryBot.create(:order) } - - it "is valid with valid attributes" do - should be_valid - end - - it "is not valid without a name" do - should validate_presence_of(:name) - end - - it "has one higher order taxon" do - should belong_to(:higher_order_taxon) - end - - it "has one taxonomic class" do - should belong_to(:taxonomic_class) - end - - it "has many families" do - should have_many(:families) - end - - it "has many species" do - should have_many(:species) - end - - context "returns number of orders in higher order taxon" do - before(:each) { @hot = FactoryBot.create(:higher_order_taxon) } - - it "returns correct number of orders in higher order taxon" do - FactoryBot.create(:order, higher_order_taxon: @hot) - FactoryBot.create(:order, higher_order_taxon: @hot) - FactoryBot.create(:order, higher_order_taxon: @hot) - - expect(Order.in_higher_order_taxon(@hot.id)).to be == 3 - end - - it "returns correct number for no orders in higher order taxon" do - expect(Order.in_higher_order_taxon(@hot.id)).to be == 0 - end - end -end \ No newline at end of file diff --git a/spec/models/species_spec.rb b/spec/models/species_spec.rb deleted file mode 100644 index b7412661..00000000 --- a/spec/models/species_spec.rb +++ /dev/null @@ -1,178 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'rails_helper' -require Rails.root.join "spec/concerns/project_record_spec.rb" - -RSpec.describe Species do - before(:all) { Project.create(name: 'All') } - it_behaves_like "project_record" - - subject { FactoryBot.create(:species) } - - it "is valid with valid attributes" do - should be_valid - end - - it "assigns display names after save" do - should callback(:assign_display_names).before(:save) - end - - it "has many individuals" do - should have_many(:individuals) - end - - it "has many primer pos on genome" do - should have_many(:primer_pos_on_genomes) - end - - it "belongs to a family" do - should belong_to(:family) - end - - context "returns number of species in higher order taxon" do - before(:each) { @hot = FactoryBot.create(:higher_order_taxon) } - - it "returns correct number of species in higher order taxon" do - order = FactoryBot.create(:order, higher_order_taxon: @hot) - family1 = FactoryBot.create(:family, order: order) - family2 = FactoryBot.create(:family, order: order) - - species1 = FactoryBot.create(:species_with_taxonomy, family: family1, infraspecific: 'sub_a') - species2 = species1.dup - species2.update(infraspecific: 'sub_b') - - FactoryBot.create(:species_with_taxonomy, family: family2) - - expect(Species.spp_in_higher_order_taxon(@hot.id)).to be == [2, 3] - end - - it "returns correct number for no species in higher order taxon" do - expect(Species.spp_in_higher_order_taxon(@hot.id)).to be == [0, 0] - end - end - - context "returns associated family name" do - it "returns name of associated family if one exists" do - family = FactoryBot.create(:family) - species = FactoryBot.create(:species, family: family) - - expect(species.family_name).to be == species.family.name - end - - it "returns nil if no associated family exists" do - species = FactoryBot.create(:species, family: nil) - expect(species.family_name).to be == nil - end - end - - context "changes associated family name" do - it "changes name of associated family if one exists" do - family1 = FactoryBot.create(:family) - family2 = FactoryBot.create(:family) - species = FactoryBot.create(:species, family: family1) - - expect { species.family_name = family2.name }.to change { species.family }.to family2 - end - - it "creates new associated family if none exists" do - family_name = Faker::Lorem.word - - expect { subject.family_name = family_name }.to change { Family.count }.by 1 - end - - it "does not change associated family if nil is provided" do - family = FactoryBot.create(:family) - species = FactoryBot.create(:species, family: family) - - expect { species.family_name = nil }.not_to change { species.family } - end - - it "removes associated family if an empty string is provided" do - family = FactoryBot.create(:family) - species = FactoryBot.create(:species, family: family) - - expect { species.family_name = '' }.to change { species.family }.to nil - end - end - - context "returns a species full name" do - it "returns full name with all parts" do - species = FactoryBot.create(:species) - expect(species.full_name).to be == "#{species.genus_name} #{species.species_epithet} #{species.infraspecific}" - end - - it "returns binomial" do - species = FactoryBot.create(:species, infraspecific: nil) - expect(species.full_name).to be == "#{species.genus_name} #{species.species_epithet}" - end - - it "returns genus" do - species = FactoryBot.create(:species, species_epithet: nil, infraspecific: nil) - expect(species.full_name).to be == "#{species.genus_name}" - end - - it "returns empty string if no name parts are available" do - species = FactoryBot.create(:species, genus_name: nil, species_epithet: nil, infraspecific: nil) - expect(species.full_name).to be == "" - end - end - - context "returns the species component of a species name" do - it "returns species component with all parts" do - species = FactoryBot.create(:species) - expect(species.get_species_component).to be == "#{species.genus_name} #{species.species_epithet}" - end - - it "returns genus" do - species = FactoryBot.create(:species, species_epithet: nil) - expect(species.get_species_component).to be == "#{species.genus_name}" - end - - it "returns empty string if no name parts are available" do - species = FactoryBot.create(:species, genus_name: nil, species_epithet: nil) - expect(species.get_species_component).to be == "" - end - end - - context "returns a species name for display" do - it "returns binomial if no intraspecific is available" do - species = FactoryBot.create(:species, infraspecific: nil) - expect(species.name_for_display).to be == "#{species.genus_name} #{species.species_epithet}" - - species = FactoryBot.create(:species, infraspecific: '') - expect(species.name_for_display).to be == "#{species.genus_name} #{species.species_epithet}" - end - - it "returns name with variety info if comment indicates a variety" do - species = FactoryBot.create(:species, comment: "blablabla\n - is a variety") - expect(species.name_for_display).to be == "#{species.genus_name} #{species.species_epithet} var. #{species.infraspecific}" - end - - it "returns name with subspecies indicator otherwise" do - species = FactoryBot.create(:species) - expect(species.name_for_display).to be == "#{species.genus_name} #{species.species_epithet} ssp. #{species.infraspecific}" - end - end - - xit "imports species data" -end \ No newline at end of file diff --git a/spec/models/subdivision_spec.rb b/spec/models/subdivision_spec.rb deleted file mode 100644 index 782e91d4..00000000 --- a/spec/models/subdivision_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'rails_helper' - -RSpec.describe Subdivision do - subject { FactoryBot.create(:subdivision) } - - it "is valid with valid attributes" do - should be_valid - end - - it "belong to one division" do - should belong_to(:division) - end - - it "has many taxonomic classes" do - should have_many(:taxonomic_classes) - end -end \ No newline at end of file diff --git a/spec/models/taxonomic_class_spec.rb b/spec/models/taxonomic_class_spec.rb deleted file mode 100644 index 1b4ee6e6..00000000 --- a/spec/models/taxonomic_class_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Barcode Workflow Manager - A web framework to assemble, analyze and manage DNA -# barcode data and metadata. -# Copyright (C) 2020 Kai Müller , Sarah Wiechers -# -# -# This file is part of Barcode Workflow Manager. -# -# Barcode Workflow Manager is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Barcode Workflow Manager is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Barcode Workflow Manager. If not, see -# . -# -require 'rails_helper' - -RSpec.describe TaxonomicClass do - subject { FactoryBot.create(:taxonomic_class) } - - it "is valid with valid attributes" do - should be_valid - end - - it "belong to a subdivision" do - should belong_to(:subdivision) - end - - it "has many orders" do - should have_many(:orders) - end -end \ No newline at end of file diff --git a/spec/requests/taxon_request_spec.rb b/spec/requests/taxon_request_spec.rb deleted file mode 100644 index cc0e2661..00000000 --- a/spec/requests/taxon_request_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe "Taxa", type: :request do - -end diff --git a/vendor/assets/javascripts/chosen.jquery.js b/vendor/assets/javascripts/chosen.jquery.js deleted file mode 100755 index a0d71d8a..00000000 --- a/vendor/assets/javascripts/chosen.jquery.js +++ /dev/null @@ -1,1211 +0,0 @@ -/*! -Chosen, a Select Box Enhancer for jQuery and Prototype -by Patrick Filler for Harvest, http://getharvest.com - -Version 1.1.0 -Full source at https://github.com/harvesthq/chosen -Copyright (c) 2011 Harvest http://getharvest.com - -MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md -This file is generated by `grunt build`, do not edit it by hand. -*/ - -(function() { - var $, AbstractChosen, Chosen, SelectParser, _ref, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - SelectParser = (function() { - function SelectParser() { - this.options_index = 0; - this.parsed = []; - } - - SelectParser.prototype.add_node = function(child) { - if (child.nodeName.toUpperCase() === "OPTGROUP") { - return this.add_group(child); - } else { - return this.add_option(child); - } - }; - - SelectParser.prototype.add_group = function(group) { - var group_position, option, _i, _len, _ref, _results; - group_position = this.parsed.length; - this.parsed.push({ - array_index: group_position, - group: true, - label: this.escapeExpression(group.label), - children: 0, - disabled: group.disabled - }); - _ref = group.childNodes; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - option = _ref[_i]; - _results.push(this.add_option(option, group_position, group.disabled)); - } - return _results; - }; - - SelectParser.prototype.add_option = function(option, group_position, group_disabled) { - if (option.nodeName.toUpperCase() === "OPTION") { - if (option.text !== "") { - if (group_position != null) { - this.parsed[group_position].children += 1; - } - this.parsed.push({ - array_index: this.parsed.length, - options_index: this.options_index, - value: option.value, - text: option.text, - html: option.innerHTML, - selected: option.selected, - disabled: group_disabled === true ? group_disabled : option.disabled, - group_array_index: group_position, - classes: option.className, - style: option.style.cssText - }); - } else { - this.parsed.push({ - array_index: this.parsed.length, - options_index: this.options_index, - empty: true - }); - } - return this.options_index += 1; - } - }; - - SelectParser.prototype.escapeExpression = function(text) { - var map, unsafe_chars; - if ((text == null) || text === false) { - return ""; - } - if (!/[\&\<\>\"\'\`]/.test(text)) { - return text; - } - map = { - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g; - return text.replace(unsafe_chars, function(chr) { - return map[chr] || "&"; - }); - }; - - return SelectParser; - - })(); - - SelectParser.select_to_array = function(select) { - var child, parser, _i, _len, _ref; - parser = new SelectParser(); - _ref = select.childNodes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - parser.add_node(child); - } - return parser.parsed; - }; - - AbstractChosen = (function() { - function AbstractChosen(form_field, options) { - this.form_field = form_field; - this.options = options != null ? options : {}; - if (!AbstractChosen.browser_is_supported()) { - return; - } - this.is_multiple = this.form_field.multiple; - this.set_default_text(); - this.set_default_values(); - this.setup(); - this.set_up_html(); - this.register_observers(); - } - - AbstractChosen.prototype.set_default_values = function() { - var _this = this; - this.click_test_action = function(evt) { - return _this.test_active_click(evt); - }; - this.activate_action = function(evt) { - return _this.activate_field(evt); - }; - this.active_field = false; - this.mouse_on_container = false; - this.results_showing = false; - this.result_highlighted = null; - this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false; - this.disable_search_threshold = this.options.disable_search_threshold || 0; - this.disable_search = this.options.disable_search || false; - this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true; - this.group_search = this.options.group_search != null ? this.options.group_search : true; - this.search_contains = this.options.search_contains || false; - this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true; - this.max_selected_options = this.options.max_selected_options || Infinity; - this.inherit_select_classes = this.options.inherit_select_classes || false; - this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true; - return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true; - }; - - AbstractChosen.prototype.set_default_text = function() { - if (this.form_field.getAttribute("data-placeholder")) { - this.default_text = this.form_field.getAttribute("data-placeholder"); - } else if (this.is_multiple) { - this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text; - } else { - this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text; - } - return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text; - }; - - AbstractChosen.prototype.mouse_enter = function() { - return this.mouse_on_container = true; - }; - - AbstractChosen.prototype.mouse_leave = function() { - return this.mouse_on_container = false; - }; - - AbstractChosen.prototype.input_focus = function(evt) { - var _this = this; - if (this.is_multiple) { - if (!this.active_field) { - return setTimeout((function() { - return _this.container_mousedown(); - }), 50); - } - } else { - if (!this.active_field) { - return this.activate_field(); - } - } - }; - - AbstractChosen.prototype.input_blur = function(evt) { - var _this = this; - if (!this.mouse_on_container) { - this.active_field = false; - return setTimeout((function() { - return _this.blur_test(); - }), 100); - } - }; - - AbstractChosen.prototype.results_option_build = function(options) { - var content, data, _i, _len, _ref; - content = ''; - _ref = this.results_data; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - data = _ref[_i]; - if (data.group) { - content += this.result_add_group(data); - } else { - content += this.result_add_option(data); - } - if (options != null ? options.first : void 0) { - if (data.selected && this.is_multiple) { - this.choice_build(data); - } else if (data.selected && !this.is_multiple) { - this.single_set_selected_text(data.text); - } - } - } - return content; - }; - - AbstractChosen.prototype.result_add_option = function(option) { - var classes, option_el; - if (!option.search_match) { - return ''; - } - if (!this.include_option_in_results(option)) { - return ''; - } - classes = []; - if (!option.disabled && !(option.selected && this.is_multiple)) { - classes.push("active-result"); - } - if (option.disabled && !(option.selected && this.is_multiple)) { - classes.push("disabled-result"); - } - if (option.selected) { - classes.push("result-selected"); - } - if (option.group_array_index != null) { - classes.push("group-option"); - } - if (option.classes !== "") { - classes.push(option.classes); - } - option_el = document.createElement("li"); - option_el.className = classes.join(" "); - option_el.style.cssText = option.style; - option_el.setAttribute("data-option-array-index", option.array_index); - option_el.innerHTML = option.search_text; - return this.outerHTML(option_el); - }; - - AbstractChosen.prototype.result_add_group = function(group) { - var group_el; - if (!(group.search_match || group.group_match)) { - return ''; - } - if (!(group.active_options > 0)) { - return ''; - } - group_el = document.createElement("li"); - group_el.className = "group-result"; - group_el.innerHTML = group.search_text; - return this.outerHTML(group_el); - }; - - AbstractChosen.prototype.results_update_field = function() { - this.set_default_text(); - if (!this.is_multiple) { - this.results_reset_cleanup(); - } - this.result_clear_highlight(); - this.results_build(); - if (this.results_showing) { - return this.winnow_results(); - } - }; - - AbstractChosen.prototype.reset_single_select_options = function() { - var result, _i, _len, _ref, _results; - _ref = this.results_data; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - result = _ref[_i]; - if (result.selected) { - _results.push(result.selected = false); - } else { - _results.push(void 0); - } - } - return _results; - }; - - AbstractChosen.prototype.results_toggle = function() { - if (this.results_showing) { - return this.results_hide(); - } else { - return this.results_show(); - } - }; - - AbstractChosen.prototype.results_search = function(evt) { - if (this.results_showing) { - return this.winnow_results(); - } else { - return this.results_show(); - } - }; - - AbstractChosen.prototype.winnow_results = function() { - var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref; - this.no_results_clear(); - results = 0; - searchText = this.get_search_text(); - escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); - regexAnchor = this.search_contains ? "" : "^"; - regex = new RegExp(regexAnchor + escapedSearchText, 'i'); - zregex = new RegExp(escapedSearchText, 'i'); - _ref = this.results_data; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - option = _ref[_i]; - option.search_match = false; - results_group = null; - if (this.include_option_in_results(option)) { - if (option.group) { - option.group_match = false; - option.active_options = 0; - } - if ((option.group_array_index != null) && this.results_data[option.group_array_index]) { - results_group = this.results_data[option.group_array_index]; - if (results_group.active_options === 0 && results_group.search_match) { - results += 1; - } - results_group.active_options += 1; - } - if (!(option.group && !this.group_search)) { - option.search_text = option.group ? option.label : option.html; - option.search_match = this.search_string_match(option.search_text, regex); - if (option.search_match && !option.group) { - results += 1; - } - if (option.search_match) { - if (searchText.length) { - startpos = option.search_text.search(zregex); - text = option.search_text.substr(0, startpos + searchText.length) + '' + option.search_text.substr(startpos + searchText.length); - option.search_text = text.substr(0, startpos) + '' + text.substr(startpos); - } - if (results_group != null) { - results_group.group_match = true; - } - } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) { - option.search_match = true; - } - } - } - } - this.result_clear_highlight(); - if (results < 1 && searchText.length) { - this.update_results_content(""); - return this.no_results(searchText); - } else { - this.update_results_content(this.results_option_build()); - return this.winnow_results_set_highlight(); - } - }; - - AbstractChosen.prototype.search_string_match = function(search_string, regex) { - var part, parts, _i, _len; - if (regex.test(search_string)) { - return true; - } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) { - parts = search_string.replace(/\[|\]/g, "").split(" "); - if (parts.length) { - for (_i = 0, _len = parts.length; _i < _len; _i++) { - part = parts[_i]; - if (regex.test(part)) { - return true; - } - } - } - } - }; - - AbstractChosen.prototype.choices_count = function() { - var option, _i, _len, _ref; - if (this.selected_option_count != null) { - return this.selected_option_count; - } - this.selected_option_count = 0; - _ref = this.form_field.options; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - option = _ref[_i]; - if (option.selected) { - this.selected_option_count += 1; - } - } - return this.selected_option_count; - }; - - AbstractChosen.prototype.choices_click = function(evt) { - evt.preventDefault(); - if (!(this.results_showing || this.is_disabled)) { - return this.results_show(); - } - }; - - AbstractChosen.prototype.keyup_checker = function(evt) { - var stroke, _ref; - stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; - this.search_field_scale(); - switch (stroke) { - case 8: - if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) { - return this.keydown_backstroke(); - } else if (!this.pending_backstroke) { - this.result_clear_highlight(); - return this.results_search(); - } - break; - case 13: - evt.preventDefault(); - if (this.results_showing) { - return this.result_select(evt); - } - break; - case 27: - if (this.results_showing) { - this.results_hide(); - } - return true; - case 9: - case 38: - case 40: - case 16: - case 91: - case 17: - break; - default: - return this.results_search(); - } - }; - - AbstractChosen.prototype.clipboard_event_checker = function(evt) { - var _this = this; - return setTimeout((function() { - return _this.results_search(); - }), 50); - }; - - AbstractChosen.prototype.container_width = function() { - if (this.options.width != null) { - return this.options.width; - } else { - return "" + this.form_field.offsetWidth + "px"; - } - }; - - AbstractChosen.prototype.include_option_in_results = function(option) { - if (this.is_multiple && (!this.display_selected_options && option.selected)) { - return false; - } - if (!this.display_disabled_options && option.disabled) { - return false; - } - if (option.empty) { - return false; - } - return true; - }; - - AbstractChosen.prototype.search_results_touchstart = function(evt) { - this.touch_started = true; - return this.search_results_mouseover(evt); - }; - - AbstractChosen.prototype.search_results_touchmove = function(evt) { - this.touch_started = false; - return this.search_results_mouseout(evt); - }; - - AbstractChosen.prototype.search_results_touchend = function(evt) { - if (this.touch_started) { - return this.search_results_mouseup(evt); - } - }; - - AbstractChosen.prototype.outerHTML = function(element) { - var tmp; - if (element.outerHTML) { - return element.outerHTML; - } - tmp = document.createElement("div"); - tmp.appendChild(element); - return tmp.innerHTML; - }; - - AbstractChosen.browser_is_supported = function() { - if (window.navigator.appName === "Microsoft Internet Explorer") { - return document.documentMode >= 8; - } - if (/iP(od|hone)/i.test(window.navigator.userAgent)) { - return false; - } - if (/Android/i.test(window.navigator.userAgent)) { - if (/Mobile/i.test(window.navigator.userAgent)) { - return false; - } - } - return true; - }; - - AbstractChosen.default_multiple_text = "Select Some Options"; - - AbstractChosen.default_single_text = "Select an Option"; - - AbstractChosen.default_no_result_text = "No results match"; - - return AbstractChosen; - - })(); - - $ = jQuery; - - $.fn.extend({ - chosen: function(options) { - if (!AbstractChosen.browser_is_supported()) { - return this; - } - return this.each(function(input_field) { - var $this, chosen; - $this = $(this); - chosen = $this.data('chosen'); - if (options === 'destroy' && chosen) { - chosen.destroy(); - } else if (!chosen) { - $this.data('chosen', new Chosen(this, options)); - } - }); - } - }); - - Chosen = (function(_super) { - __extends(Chosen, _super); - - function Chosen() { - _ref = Chosen.__super__.constructor.apply(this, arguments); - return _ref; - } - - Chosen.prototype.setup = function() { - this.form_field_jq = $(this.form_field); - this.current_selectedIndex = this.form_field.selectedIndex; - return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl"); - }; - - Chosen.prototype.set_up_html = function() { - var container_classes, container_props; - container_classes = ["chosen-container"]; - container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single")); - if (this.inherit_select_classes && this.form_field.className) { - container_classes.push(this.form_field.className); - } - if (this.is_rtl) { - container_classes.push("chosen-rtl"); - } - container_props = { - 'class': container_classes.join(' '), - 'style': "width: " + (this.container_width()) + ";", - 'title': this.form_field.title - }; - if (this.form_field.id.length) { - container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen"; - } - this.container = $("
", container_props); - if (this.is_multiple) { - this.container.html('
    '); - } else { - this.container.html('' + this.default_text + '
      '); - } - this.form_field_jq.hide().after(this.container); - this.dropdown = this.container.find('div.chosen-drop').first(); - this.search_field = this.container.find('input').first(); - this.search_results = this.container.find('ul.chosen-results').first(); - this.search_field_scale(); - this.search_no_results = this.container.find('li.no-results').first(); - if (this.is_multiple) { - this.search_choices = this.container.find('ul.chosen-choices').first(); - this.search_container = this.container.find('li.search-field').first(); - } else { - this.search_container = this.container.find('div.chosen-search').first(); - this.selected_item = this.container.find('.chosen-single').first(); - } - this.results_build(); - this.set_tab_index(); - this.set_label_behavior(); - return this.form_field_jq.trigger("chosen:ready", { - chosen: this - }); - }; - - Chosen.prototype.register_observers = function() { - var _this = this; - this.container.bind('mousedown.chosen', function(evt) { - _this.container_mousedown(evt); - }); - this.container.bind('mouseup.chosen', function(evt) { - _this.container_mouseup(evt); - }); - this.container.bind('mouseenter.chosen', function(evt) { - _this.mouse_enter(evt); - }); - this.container.bind('mouseleave.chosen', function(evt) { - _this.mouse_leave(evt); - }); - this.search_results.bind('mouseup.chosen', function(evt) { - _this.search_results_mouseup(evt); - }); - this.search_results.bind('mouseover.chosen', function(evt) { - _this.search_results_mouseover(evt); - }); - this.search_results.bind('mouseout.chosen', function(evt) { - _this.search_results_mouseout(evt); - }); - this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) { - _this.search_results_mousewheel(evt); - }); - this.search_results.bind('touchstart.chosen', function(evt) { - _this.search_results_touchstart(evt); - }); - this.search_results.bind('touchmove.chosen', function(evt) { - _this.search_results_touchmove(evt); - }); - this.search_results.bind('touchend.chosen', function(evt) { - _this.search_results_touchend(evt); - }); - this.form_field_jq.bind("chosen:updated.chosen", function(evt) { - _this.results_update_field(evt); - }); - this.form_field_jq.bind("chosen:activate.chosen", function(evt) { - _this.activate_field(evt); - }); - this.form_field_jq.bind("chosen:open.chosen", function(evt) { - _this.container_mousedown(evt); - }); - this.form_field_jq.bind("chosen:close.chosen", function(evt) { - _this.input_blur(evt); - }); - this.search_field.bind('blur.chosen', function(evt) { - _this.input_blur(evt); - }); - this.search_field.bind('keyup.chosen', function(evt) { - _this.keyup_checker(evt); - }); - this.search_field.bind('keydown.chosen', function(evt) { - _this.keydown_checker(evt); - }); - this.search_field.bind('focus.chosen', function(evt) { - _this.input_focus(evt); - }); - this.search_field.bind('cut.chosen', function(evt) { - _this.clipboard_event_checker(evt); - }); - this.search_field.bind('paste.chosen', function(evt) { - _this.clipboard_event_checker(evt); - }); - if (this.is_multiple) { - return this.search_choices.bind('click.chosen', function(evt) { - _this.choices_click(evt); - }); - } else { - return this.container.bind('click.chosen', function(evt) { - evt.preventDefault(); - }); - } - }; - - Chosen.prototype.destroy = function() { - $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); - if (this.search_field[0].tabIndex) { - this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex; - } - this.container.remove(); - this.form_field_jq.removeData('chosen'); - return this.form_field_jq.show(); - }; - - Chosen.prototype.search_field_disabled = function() { - this.is_disabled = this.form_field_jq[0].disabled; - if (this.is_disabled) { - this.container.addClass('chosen-disabled'); - this.search_field[0].disabled = true; - if (!this.is_multiple) { - this.selected_item.unbind("focus.chosen", this.activate_action); - } - return this.close_field(); - } else { - this.container.removeClass('chosen-disabled'); - this.search_field[0].disabled = false; - if (!this.is_multiple) { - return this.selected_item.bind("focus.chosen", this.activate_action); - } - } - }; - - Chosen.prototype.container_mousedown = function(evt) { - if (!this.is_disabled) { - if (evt && evt.type === "mousedown" && !this.results_showing) { - evt.preventDefault(); - } - if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) { - if (!this.active_field) { - if (this.is_multiple) { - this.search_field.val(""); - } - $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action); - this.results_show(); - } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) { - evt.preventDefault(); - this.results_toggle(); - } - return this.activate_field(); - } - } - }; - - Chosen.prototype.container_mouseup = function(evt) { - if (evt.target.nodeName === "ABBR" && !this.is_disabled) { - return this.results_reset(evt); - } - }; - - Chosen.prototype.search_results_mousewheel = function(evt) { - var delta; - if (evt.originalEvent) { - delta = -evt.originalEvent.wheelDelta || evt.originalEvent.detail; - } - if (delta != null) { - evt.preventDefault(); - if (evt.type === 'DOMMouseScroll') { - delta = delta * 40; - } - return this.search_results.scrollTop(delta + this.search_results.scrollTop()); - } - }; - - Chosen.prototype.blur_test = function(evt) { - if (!this.active_field && this.container.hasClass("chosen-container-active")) { - return this.close_field(); - } - }; - - Chosen.prototype.close_field = function() { - $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); - this.active_field = false; - this.results_hide(); - this.container.removeClass("chosen-container-active"); - this.clear_backstroke(); - this.show_search_field_default(); - return this.search_field_scale(); - }; - - Chosen.prototype.activate_field = function() { - this.container.addClass("chosen-container-active"); - this.active_field = true; - this.search_field.val(this.search_field.val()); - return this.search_field.focus(); - }; - - Chosen.prototype.test_active_click = function(evt) { - var active_container; - active_container = $(evt.target).closest('.chosen-container'); - if (active_container.length && this.container[0] === active_container[0]) { - return this.active_field = true; - } else { - return this.close_field(); - } - }; - - Chosen.prototype.results_build = function() { - this.parsing = true; - this.selected_option_count = null; - this.results_data = SelectParser.select_to_array(this.form_field); - if (this.is_multiple) { - this.search_choices.find("li.search-choice").remove(); - } else if (!this.is_multiple) { - this.single_set_selected_text(); - if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) { - this.search_field[0].readOnly = true; - this.container.addClass("chosen-container-single-nosearch"); - } else { - this.search_field[0].readOnly = false; - this.container.removeClass("chosen-container-single-nosearch"); - } - } - this.update_results_content(this.results_option_build({ - first: true - })); - this.search_field_disabled(); - this.show_search_field_default(); - this.search_field_scale(); - return this.parsing = false; - }; - - Chosen.prototype.result_do_highlight = function(el) { - var high_bottom, high_top, maxHeight, visible_bottom, visible_top; - if (el.length) { - this.result_clear_highlight(); - this.result_highlight = el; - this.result_highlight.addClass("highlighted"); - maxHeight = parseInt(this.search_results.css("maxHeight"), 10); - visible_top = this.search_results.scrollTop(); - visible_bottom = maxHeight + visible_top; - high_top = this.result_highlight.position().top + this.search_results.scrollTop(); - high_bottom = high_top + this.result_highlight.outerHeight(); - if (high_bottom >= visible_bottom) { - return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0); - } else if (high_top < visible_top) { - return this.search_results.scrollTop(high_top); - } - } - }; - - Chosen.prototype.result_clear_highlight = function() { - if (this.result_highlight) { - this.result_highlight.removeClass("highlighted"); - } - return this.result_highlight = null; - }; - - Chosen.prototype.results_show = function() { - if (this.is_multiple && this.max_selected_options <= this.choices_count()) { - this.form_field_jq.trigger("chosen:maxselected", { - chosen: this - }); - return false; - } - this.container.addClass("chosen-with-drop"); - this.results_showing = true; - this.search_field.focus(); - this.search_field.val(this.search_field.val()); - this.winnow_results(); - return this.form_field_jq.trigger("chosen:showing_dropdown", { - chosen: this - }); - }; - - Chosen.prototype.update_results_content = function(content) { - return this.search_results.html(content); - }; - - Chosen.prototype.results_hide = function() { - if (this.results_showing) { - this.result_clear_highlight(); - this.container.removeClass("chosen-with-drop"); - this.form_field_jq.trigger("chosen:hiding_dropdown", { - chosen: this - }); - } - return this.results_showing = false; - }; - - Chosen.prototype.set_tab_index = function(el) { - var ti; - if (this.form_field.tabIndex) { - ti = this.form_field.tabIndex; - this.form_field.tabIndex = -1; - return this.search_field[0].tabIndex = ti; - } - }; - - Chosen.prototype.set_label_behavior = function() { - var _this = this; - this.form_field_label = this.form_field_jq.parents("label"); - if (!this.form_field_label.length && this.form_field.id.length) { - this.form_field_label = $("label[for='" + this.form_field.id + "']"); - } - if (this.form_field_label.length > 0) { - return this.form_field_label.bind('click.chosen', function(evt) { - if (_this.is_multiple) { - return _this.container_mousedown(evt); - } else { - return _this.activate_field(); - } - }); - } - }; - - Chosen.prototype.show_search_field_default = function() { - if (this.is_multiple && this.choices_count() < 1 && !this.active_field) { - this.search_field.val(this.default_text); - return this.search_field.addClass("default"); - } else { - this.search_field.val(""); - return this.search_field.removeClass("default"); - } - }; - - Chosen.prototype.search_results_mouseup = function(evt) { - var target; - target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); - if (target.length) { - this.result_highlight = target; - this.result_select(evt); - return this.search_field.focus(); - } - }; - - Chosen.prototype.search_results_mouseover = function(evt) { - var target; - target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); - if (target) { - return this.result_do_highlight(target); - } - }; - - Chosen.prototype.search_results_mouseout = function(evt) { - if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) { - return this.result_clear_highlight(); - } - }; - - Chosen.prototype.choice_build = function(item) { - var choice, close_link, - _this = this; - choice = $('
    • ', { - "class": "search-choice" - }).html("" + item.html + ""); - if (item.disabled) { - choice.addClass('search-choice-disabled'); - } else { - close_link = $('', { - "class": 'search-choice-close', - 'data-option-array-index': item.array_index - }); - close_link.bind('click.chosen', function(evt) { - return _this.choice_destroy_link_click(evt); - }); - choice.append(close_link); - } - return this.search_container.before(choice); - }; - - Chosen.prototype.choice_destroy_link_click = function(evt) { - evt.preventDefault(); - evt.stopPropagation(); - if (!this.is_disabled) { - return this.choice_destroy($(evt.target)); - } - }; - - Chosen.prototype.choice_destroy = function(link) { - if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) { - this.show_search_field_default(); - if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) { - this.results_hide(); - } - link.parents('li').first().remove(); - return this.search_field_scale(); - } - }; - - Chosen.prototype.results_reset = function() { - this.reset_single_select_options(); - this.form_field.options[0].selected = true; - this.single_set_selected_text(); - this.show_search_field_default(); - this.results_reset_cleanup(); - this.form_field_jq.trigger("change"); - if (this.active_field) { - return this.results_hide(); - } - }; - - Chosen.prototype.results_reset_cleanup = function() { - this.current_selectedIndex = this.form_field.selectedIndex; - return this.selected_item.find("abbr").remove(); - }; - - Chosen.prototype.result_select = function(evt) { - var high, item; - if (this.result_highlight) { - high = this.result_highlight; - this.result_clear_highlight(); - if (this.is_multiple && this.max_selected_options <= this.choices_count()) { - this.form_field_jq.trigger("chosen:maxselected", { - chosen: this - }); - return false; - } - if (this.is_multiple) { - high.removeClass("active-result"); - } else { - this.reset_single_select_options(); - } - item = this.results_data[high[0].getAttribute("data-option-array-index")]; - item.selected = true; - this.form_field.options[item.options_index].selected = true; - this.selected_option_count = null; - if (this.is_multiple) { - this.choice_build(item); - } else { - this.single_set_selected_text(item.text); - } - if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) { - this.results_hide(); - } - this.search_field.val(""); - if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) { - this.form_field_jq.trigger("change", { - 'selected': this.form_field.options[item.options_index].value - }); - } - this.current_selectedIndex = this.form_field.selectedIndex; - return this.search_field_scale(); - } - }; - - Chosen.prototype.single_set_selected_text = function(text) { - if (text == null) { - text = this.default_text; - } - if (text === this.default_text) { - this.selected_item.addClass("chosen-default"); - } else { - this.single_deselect_control_build(); - this.selected_item.removeClass("chosen-default"); - } - return this.selected_item.find("span").text(text); - }; - - Chosen.prototype.result_deselect = function(pos) { - var result_data; - result_data = this.results_data[pos]; - if (!this.form_field.options[result_data.options_index].disabled) { - result_data.selected = false; - this.form_field.options[result_data.options_index].selected = false; - this.selected_option_count = null; - this.result_clear_highlight(); - if (this.results_showing) { - this.winnow_results(); - } - this.form_field_jq.trigger("change", { - deselected: this.form_field.options[result_data.options_index].value - }); - this.search_field_scale(); - return true; - } else { - return false; - } - }; - - Chosen.prototype.single_deselect_control_build = function() { - if (!this.allow_single_deselect) { - return; - } - if (!this.selected_item.find("abbr").length) { - this.selected_item.find("span").first().after(""); - } - return this.selected_item.addClass("chosen-single-with-deselect"); - }; - - Chosen.prototype.get_search_text = function() { - if (this.search_field.val() === this.default_text) { - return ""; - } else { - return $('
      ').text($.trim(this.search_field.val())).html(); - } - }; - - Chosen.prototype.winnow_results_set_highlight = function() { - var do_high, selected_results; - selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; - do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); - if (do_high != null) { - return this.result_do_highlight(do_high); - } - }; - - Chosen.prototype.no_results = function(terms) { - var no_results_html; - no_results_html = $('
    • ' + this.results_none_found + ' ""
    • '); - no_results_html.find("span").first().html(terms); - this.search_results.append(no_results_html); - return this.form_field_jq.trigger("chosen:no_results", { - chosen: this - }); - }; - - Chosen.prototype.no_results_clear = function() { - return this.search_results.find(".no-results").remove(); - }; - - Chosen.prototype.keydown_arrow = function() { - var next_sib; - if (this.results_showing && this.result_highlight) { - next_sib = this.result_highlight.nextAll("li.active-result").first(); - if (next_sib) { - return this.result_do_highlight(next_sib); - } - } else { - return this.results_show(); - } - }; - - Chosen.prototype.keyup_arrow = function() { - var prev_sibs; - if (!this.results_showing && !this.is_multiple) { - return this.results_show(); - } else if (this.result_highlight) { - prev_sibs = this.result_highlight.prevAll("li.active-result"); - if (prev_sibs.length) { - return this.result_do_highlight(prev_sibs.first()); - } else { - if (this.choices_count() > 0) { - this.results_hide(); - } - return this.result_clear_highlight(); - } - } - }; - - Chosen.prototype.keydown_backstroke = function() { - var next_available_destroy; - if (this.pending_backstroke) { - this.choice_destroy(this.pending_backstroke.find("a").first()); - return this.clear_backstroke(); - } else { - next_available_destroy = this.search_container.siblings("li.search-choice").last(); - if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) { - this.pending_backstroke = next_available_destroy; - if (this.single_backstroke_delete) { - return this.keydown_backstroke(); - } else { - return this.pending_backstroke.addClass("search-choice-focus"); - } - } - } - }; - - Chosen.prototype.clear_backstroke = function() { - if (this.pending_backstroke) { - this.pending_backstroke.removeClass("search-choice-focus"); - } - return this.pending_backstroke = null; - }; - - Chosen.prototype.keydown_checker = function(evt) { - var stroke, _ref1; - stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode; - this.search_field_scale(); - if (stroke !== 8 && this.pending_backstroke) { - this.clear_backstroke(); - } - switch (stroke) { - case 8: - this.backstroke_length = this.search_field.val().length; - break; - case 9: - if (this.results_showing && !this.is_multiple) { - this.result_select(evt); - } - this.mouse_on_container = false; - break; - case 13: - evt.preventDefault(); - break; - case 38: - evt.preventDefault(); - this.keyup_arrow(); - break; - case 40: - evt.preventDefault(); - this.keydown_arrow(); - break; - } - }; - - Chosen.prototype.search_field_scale = function() { - var div, f_width, h, style, style_block, styles, w, _i, _len; - if (this.is_multiple) { - h = 0; - w = 0; - style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"; - styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing']; - for (_i = 0, _len = styles.length; _i < _len; _i++) { - style = styles[_i]; - style_block += style + ":" + this.search_field.css(style) + ";"; - } - div = $('
      ', { - 'style': style_block - }); - div.text(this.search_field.val()); - $('body').append(div); - w = div.width() + 25; - div.remove(); - f_width = this.container.outerWidth(); - if (w > f_width - 10) { - w = f_width - 10; - } - return this.search_field.css({ - 'width': w + 'px' - }); - } - }; - - return Chosen; - - })(AbstractChosen); - -}).call(this); diff --git a/vendor/assets/stylesheets/chosen.css.scss b/vendor/assets/stylesheets/chosen.css.scss deleted file mode 100755 index dd4328fa..00000000 --- a/vendor/assets/stylesheets/chosen.css.scss +++ /dev/null @@ -1,435 +0,0 @@ -/*! -Chosen, a Select Box Enhancer for jQuery and Prototype -by Patrick Filler for Harvest, http://getharvest.com - -Version 1.1.0 -Full source at https://github.com/harvesthq/chosen -Copyright (c) 2011 Harvest http://getharvest.com - -MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md -This file is generated by `grunt build`, do not edit it by hand. -*/ - -/* @group Base */ -.chosen-container { - position: relative; - display: inline-block; - vertical-align: middle; - font-size: 13px; - zoom: 1; - *display: inline; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} -.chosen-container .chosen-drop { - position: absolute; - top: 100%; - left: -9999px; - z-index: 1010; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100%; - border: 1px solid #aaa; - border-top: 0; - background: #fff; - box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); -} -.chosen-container.chosen-with-drop .chosen-drop { - left: 0; -} -.chosen-container a { - cursor: pointer; -} - -/* @end */ -/* @group Single Chosen */ -.chosen-container-single .chosen-single { - position: relative; - display: block; - overflow: hidden; - padding: 0 0 0 8px; - height: 23px; - border: 1px solid #aaa; - border-radius: 5px; - background-color: #fff; - background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4)); - background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background-clip: padding-box; - box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1); - color: #444; - text-decoration: none; - white-space: nowrap; - line-height: 24px; -} -.chosen-container-single .chosen-default { - color: #999; -} -.chosen-container-single .chosen-single span { - display: block; - overflow: hidden; - margin-right: 26px; - text-overflow: ellipsis; - white-space: nowrap; -} -.chosen-container-single .chosen-single-with-deselect span { - margin-right: 38px; -} -.chosen-container-single .chosen-single abbr { - position: absolute; - top: 6px; - right: 26px; - display: block; - width: 12px; - height: 12px; - background: image-url("chosen-sprite.png") -42px 1px no-repeat; - font-size: 1px; -} -.chosen-container-single .chosen-single abbr:hover { - background-position: -42px -10px; -} -.chosen-container-single.chosen-disabled .chosen-single abbr:hover { - background-position: -42px -10px; -} -.chosen-container-single .chosen-single div { - position: absolute; - top: 0; - right: 0; - display: block; - width: 18px; - height: 100%; -} -.chosen-container-single .chosen-single div b { - display: block; - width: 100%; - height: 100%; - background: image-url("chosen-sprite.png") no-repeat 0px 2px; -} -.chosen-container-single .chosen-search { - position: relative; - z-index: 1010; - margin: 0; - padding: 3px 4px; - white-space: nowrap; -} -.chosen-container-single .chosen-search input[type="text"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - margin: 1px 0; - padding: 4px 20px 4px 5px; - width: 100%; - height: auto; - outline: 0; - border: 1px solid #aaa; - background: white image-url("chosen-sprite.png") no-repeat 100% -20px; - background: image-url("chosen-sprite.png") no-repeat 100% -20px; - font-size: 1em; - font-family: sans-serif; - line-height: normal; - border-radius: 0; -} -.chosen-container-single .chosen-drop { - margin-top: -1px; - border-radius: 0 0 4px 4px; - background-clip: padding-box; -} -.chosen-container-single.chosen-container-single-nosearch .chosen-search { - position: absolute; - left: -9999px; -} - -/* @end */ -/* @group Results */ -.chosen-container .chosen-results { - position: relative; - overflow-x: hidden; - overflow-y: auto; - margin: 0 4px 4px 0; - padding: 0 0 0 4px; - max-height: 240px; - -webkit-overflow-scrolling: touch; -} -.chosen-container .chosen-results li { - display: none; - margin: 0; - padding: 5px 6px; - list-style: none; - line-height: 15px; - -webkit-touch-callout: none; -} -.chosen-container .chosen-results li.active-result { - display: list-item; - cursor: pointer; -} -.chosen-container .chosen-results li.disabled-result { - display: list-item; - color: #ccc; - cursor: default; -} -.chosen-container .chosen-results li.highlighted { - background-color: #3875d7; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc)); - background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%); - background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%); - background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%); - background-image: linear-gradient(#3875d7 20%, #2a62bc 90%); - color: #fff; -} -.chosen-container .chosen-results li.no-results { - display: list-item; - background: #f4f4f4; -} -.chosen-container .chosen-results li.group-result { - display: list-item; - font-weight: bold; - cursor: default; -} -.chosen-container .chosen-results li.group-option { - padding-left: 15px; -} -.chosen-container .chosen-results li em { - font-style: normal; - text-decoration: underline; -} - -/* @end */ -/* @group Multi Chosen */ -.chosen-container-multi .chosen-choices { - position: relative; - overflow: hidden; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - margin: 0; - padding: 0; - width: 100%; - height: auto !important; - height: 1%; - border: 1px solid #aaa; - background-color: #fff; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); - background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%); - background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%); - background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%); - background-image: linear-gradient(#eeeeee 1%, #ffffff 15%); - cursor: text; -} -.chosen-container-multi .chosen-choices li { - float: left; - list-style: none; -} -.chosen-container-multi .chosen-choices li.search-field { - margin: 0; - padding: 0; - white-space: nowrap; -} -.chosen-container-multi .chosen-choices li.search-field input[type="text"] { - margin: 1px 0; - padding: 5px; - height: 15px; - outline: 0; - border: 0 !important; - background: transparent !important; - box-shadow: none; - color: #666; - font-size: 100%; - font-family: sans-serif; - line-height: normal; - border-radius: 0; -} -.chosen-container-multi .chosen-choices li.search-field .default { - color: #999; -} -.chosen-container-multi .chosen-choices li.search-choice { - position: relative; - margin: 3px 0 3px 5px; - padding: 3px 20px 3px 5px; - border: 1px solid #aaa; - border-radius: 3px; - background-color: #e4e4e4; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); - background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-clip: padding-box; - box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05); - color: #333; - line-height: 13px; - cursor: default; -} -.chosen-container-multi .chosen-choices li.search-choice .search-choice-close { - position: absolute; - top: 4px; - right: 3px; - display: block; - width: 12px; - height: 12px; - background: image-url("chosen-sprite.png") -42px 1px no-repeat; - font-size: 1px; -} -.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover { - background-position: -42px -10px; -} -.chosen-container-multi .chosen-choices li.search-choice-disabled { - padding-right: 5px; - border: 1px solid #ccc; - background-color: #e4e4e4; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); - background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - color: #666; -} -.chosen-container-multi .chosen-choices li.search-choice-focus { - background: #d4d4d4; -} -.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close { - background-position: -42px -10px; -} -.chosen-container-multi .chosen-results { - margin: 0; - padding: 0; -} -.chosen-container-multi .chosen-drop .result-selected { - display: list-item; - color: #ccc; - cursor: default; -} - -/* @end */ -/* @group Active */ -.chosen-container-active .chosen-single { - border: 1px solid #5897fb; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); -} -.chosen-container-active.chosen-with-drop .chosen-single { - border: 1px solid #aaa; - -moz-border-radius-bottomright: 0; - border-bottom-right-radius: 0; - -moz-border-radius-bottomleft: 0; - border-bottom-left-radius: 0; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff)); - background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%); - background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%); - background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%); - background-image: linear-gradient(#eeeeee 20%, #ffffff 80%); - box-shadow: 0 1px 0 #fff inset; -} -.chosen-container-active.chosen-with-drop .chosen-single div { - border-left: none; - background: transparent; -} -.chosen-container-active.chosen-with-drop .chosen-single div b { - background-position: -18px 2px; -} -.chosen-container-active .chosen-choices { - border: 1px solid #5897fb; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); -} -.chosen-container-active .chosen-choices li.search-field input[type="text"] { - color: #111 !important; -} - -/* @end */ -/* @group Disabled Support */ -.chosen-disabled { - opacity: 0.5 !important; - cursor: default; -} -.chosen-disabled .chosen-single { - cursor: default; -} -.chosen-disabled .chosen-choices .search-choice .search-choice-close { - cursor: default; -} - -/* @end */ -/* @group Right to Left */ -.chosen-rtl { - text-align: right; -} -.chosen-rtl .chosen-single { - overflow: visible; - padding: 0 8px 0 0; -} -.chosen-rtl .chosen-single span { - margin-right: 0; - margin-left: 26px; - direction: rtl; -} -.chosen-rtl .chosen-single-with-deselect span { - margin-left: 38px; -} -.chosen-rtl .chosen-single div { - right: auto; - left: 3px; -} -.chosen-rtl .chosen-single abbr { - right: auto; - left: 26px; -} -.chosen-rtl .chosen-choices li { - float: right; -} -.chosen-rtl .chosen-choices li.search-field input[type="text"] { - direction: rtl; -} -.chosen-rtl .chosen-choices li.search-choice { - margin: 3px 5px 3px 0; - padding: 3px 5px 3px 19px; -} -.chosen-rtl .chosen-choices li.search-choice .search-choice-close { - right: auto; - left: 4px; -} -.chosen-rtl.chosen-container-single-nosearch .chosen-search, -.chosen-rtl .chosen-drop { - left: 9999px; -} -.chosen-rtl.chosen-container-single .chosen-results { - margin: 0 0 4px 4px; - padding: 0 4px 0 0; -} -.chosen-rtl .chosen-results li.group-option { - padding-right: 15px; - padding-left: 0; -} -.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { - border-right: none; -} -.chosen-rtl .chosen-search input[type="text"] { - padding: 4px 5px 4px 20px; - background: white image-url("chosen-sprite.png") no-repeat -30px -20px; - background: image-url("chosen-sprite.png") no-repeat -30px -20px; - direction: rtl; -} -.chosen-rtl.chosen-container-single .chosen-single div b { - background-position: 6px 2px; -} -.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b { - background-position: -12px 2px; -} - -/* @end */ -/* @group Retina compatibility */ -@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) { - .chosen-rtl .chosen-search input[type="text"], - .chosen-container-single .chosen-single abbr, - .chosen-container-single .chosen-single div b, - .chosen-container-single .chosen-search input[type="text"], - .chosen-container-multi .chosen-choices .search-choice .search-choice-close, - .chosen-container .chosen-results-scroll-down span, - .chosen-container .chosen-results-scroll-up span { - background-image: image-url("chosen-sprite@2x.png") !important; - background-size: 52px 37px !important; - background-repeat: no-repeat !important; - } -} -/* @end */