From 64b483d41d84949aa19b9534ae01b5a7d54aca12 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Wed, 22 Jul 2020 17:51:22 -0300 Subject: [PATCH 001/189] Revert "Purge interactive keys code from development branch" This reverts commit cce1909352cc28f05b67f3d75a321dfe34036c37. --- app/assets/images/3iView1.gif | Bin 0 -> 113 bytes app/assets/images/3iView2.gif | Bin 0 -> 116 bytes .../tasks/matrix/observation_matrices.scss | 168 +++++ .../interactive_key_controller.rb | 11 + .../interactive_key/index.html.erb | 127 ++++ config/interface/hub/user_tasks.yml | 8 + config/routes/tasks.rb | 5 +- .../20200716192152_add_descriptor_weight.rb | 6 + db/schema.rb | 3 +- lib/interactive_key.rb | 690 ++++++++++++++++++ spec/lib/interactive_key_spec.rb | 86 +++ 11 files changed, 1102 insertions(+), 2 deletions(-) create mode 100755 app/assets/images/3iView1.gif create mode 100755 app/assets/images/3iView2.gif create mode 100644 app/controllers/tasks/observation_matrices/interactive_key_controller.rb create mode 100644 app/views/tasks/observation_matrices/interactive_key/index.html.erb create mode 100644 db/migrate/20200716192152_add_descriptor_weight.rb create mode 100644 lib/interactive_key.rb create mode 100644 spec/lib/interactive_key_spec.rb diff --git a/app/assets/images/3iView1.gif b/app/assets/images/3iView1.gif new file mode 100755 index 0000000000000000000000000000000000000000..fd003d01b8c52360e6be2f46e739424e8210708b GIT binary patch literal 113 zcmZ?wbhEHblw*)&XkcUjg8%>jEB<5wG8q|kKzxu41CvKj|H{*E`4=;8xz)Y;)Si5W z+N6#EWy{9S&SmPSre#UX->t2+__wZDe#K9zLl5##Xo%&yOHT02(TnxW6pp(3)@GmX Mc2>S_WmX1j02A^kCIA2c literal 0 HcmV?d00001 diff --git a/app/assets/images/3iView2.gif b/app/assets/images/3iView2.gif new file mode 100755 index 0000000000000000000000000000000000000000..df73131a459d74302432aab8ed773ef8072b1af2 GIT binary patch literal 116 zcmZ?wbhEHblw*)&XkcUjg8%>jEB<5wG8q|kKzxu41Cw`8|H{*E`4=;8xz)Y;)Smnc z0g5v^dUh^okD9b{_o25xE-shZ&>?rdeEDPF2FIB9&#G^h9eem`h0D1mfzOJwmZ~MY RJX+2@rQ`UMq9qIr)&RT6GR^=1 literal 0 HcmV?d00001 diff --git a/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss b/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss index 8220ea3db2..b3d69d3fbc 100644 --- a/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss +++ b/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss @@ -23,3 +23,171 @@ position: relative; text-align: left; } + + +#header3i { + position: fixed; + width: 100%; + height: 56px; + top: 99px; + right: 0; + bottom: auto; + left: 0; + border-bottom: 2px solid #CCCCCC; + background-color: #C0C0B0; +} + +#header3i h1 +{ + margin: 0px; + font-size: 16pt; + font-weight: bold; + text-align: center; + font-family: arial,sans-serif; + color: #004050; +} + +#header3i table { + width: 100%; + background-color: #C0C0B0; + text-align: center; + color: #004050; +} + +#characters3i { + position: fixed; + top: 157px; + bottom: 45%; + left: 0px; + right: 0px; + margin: 0px 0px 0px 0px; + width: auto; + height: auto; + padding-left: 5px; + padding-right: 12px; + background-color: #CFCFBE; + border-bottom: 2px solid #CCCCCC; + overflow: auto; +} + +div.vertical #characters3i { + position: fixed; + top: 157px; + bottom: 42px; + left: 0px; + right: 50%; + margin: 0px 0px 0px 0px; + width: auto; + height: auto; + padding-left: 5px; + padding-right: 12px; + background-color: #CFCFBE; + border-bottom: 2px solid #CCCCCC; + overflow: auto; +} + +#characters3i h1, #content h2 { + color: #C00000; +} + +#taxa1_3i { + position: fixed; + top: 55%; + bottom: 42px; + margin: 0px 0px 0px 0px; + right: 50%; + left: 0px; + width: auto; + height: auto; + padding-left: 5px; + padding-right: 12px; + background-color: #C0C0B0; + border-bottom: 2px solid #CCCCCC; + overflow: auto; +} + +div.vertical #taxa1_3i { + position: fixed; + top: 157px; + bottom: 45%; + margin: 0px 0px 0px 0px; + right: 0px; + left: 50%; + width: auto; + height: auto; + padding-left: 5px; + padding-right: 12px; + background-color: #C0C0B0; + border-left: 2px solid #CCCCCC; + border-bottom: 2px solid #CCCCCC; + overflow: auto; +} + +#taxa2_3i { + position: fixed; + top: 55%; + bottom: 42px; + margin: 0px 0px 0px 0px; + width: auto; + height: auto; + left: 50%; + right: 0px; + padding-left: 5px; + padding-right: 12px; + background-color: #C0C0B0; + border-left: 2px solid #CCCCCC; + border-bottom: 2px solid #CCCCCC; + overflow: auto; +} + +.mainfont { color: #004050;} +.red { color: #C00000; } +.redbold { color: #C00000; font-weight: bold; } + +div.i3{ + color: #004050; + font-family: arial,sans-serif; +} + +div.i3 a { color: #004050;} +div.i3 a:visited { color: #004050;} +div.i3 a:hover { color: #C00000;} + +div.help3i +{ + background-color: #CAD9EE; + height: auto; + border: 1px solid; + padding: 1px; +} + +div.helpBox3i{ + background-color: #CAD9EE; + margin-left: 10px; + max-width: 300px; + position: absolute; + display: inline-block; + border: 1px solid; + z-index:10000; +} + +.a1 a, .a2 a, .a3 a, .a0 a { + text-decoration: none; +} + +.a1 { border:2px solid transparent; } +.a2 { border:2px outset #FFFFFF; cursor: hand; } +.a3 { border:2px inset #FFFFFF; } +.a0 { border:3px solid transparent;} +.a5 { border:3px outset #FFFFFF; cursor: hand; } +.a6 { border:3px inset #FFFFFF; } + +table.key { + background-color: #CAD9DD; + text-align: center; + color: #000080; +} + +table.key td.taxon {text-align: left;} +table.key td.image {vertical-align: top;} + diff --git a/app/controllers/tasks/observation_matrices/interactive_key_controller.rb b/app/controllers/tasks/observation_matrices/interactive_key_controller.rb new file mode 100644 index 0000000000..d25911bc58 --- /dev/null +++ b/app/controllers/tasks/observation_matrices/interactive_key_controller.rb @@ -0,0 +1,11 @@ +class Tasks::ObservationMatrices::InteractiveKeyController < ApplicationController + include TaskControllerConfiguration + + # GET + def index + + @observation_matrix = ObservationMatrix.where(project_id: sessions_current_project_id, id: params[:observation_matrix_id]).first unless params[:observation_matrix_id].blank? +# redirect_to new_observation_matrix_path and return if @observation_matrix.nil? + end + +end \ No newline at end of file diff --git a/app/views/tasks/observation_matrices/interactive_key/index.html.erb b/app/views/tasks/observation_matrices/interactive_key/index.html.erb new file mode 100644 index 0000000000..f2d1b483c7 --- /dev/null +++ b/app/views/tasks/observation_matrices/interactive_key/index.html.erb @@ -0,0 +1,127 @@ +

Interactive key

+ +
+ + +
+ <%= content_tag(:h1, observation_matrix_tag(@observation_matrix), id: 'ltrSecondHeader') -%> +
+ + + + + + + + + + + + + + + +
+ Language + + + <%= image_tag('3iView2.gif', :alt => 'Change view', :id => 'k1', :style => 'opacity: 0.3') + %><%= image_tag('3iView1.gif', :alt => 'Change view', :id => 'k2', :style => 'opacity: 1') %> + + + Proceed +   + Key_Author +
+   +   +    +
Source Text
+
+
+
+
+
+
+

Remaining Taxa

+
+
+

Elimitated Taxa

+
+
+ + + + +
+ \ No newline at end of file diff --git a/config/interface/hub/user_tasks.yml b/config/interface/hub/user_tasks.yml index 2b0a480b08..20026c0a7a 100644 --- a/config/interface/hub/user_tasks.yml +++ b/config/interface/hub/user_tasks.yml @@ -444,6 +444,14 @@ index_dashboard_task: - matrix status: prototype description: 'Summarize observations across a nomenclaturally-based hierarchy.' +interactive_key_task: + hub: true + name: 'Interactive key' + related: + categories: + - matrix + status: prototype + description: 'Interactive key based on an observation matrix.' index_stats_task: hub: true name: 'Nomenclature stats' diff --git a/config/routes/tasks.rb b/config/routes/tasks.rb index 6fec7bb3ca..cdf9f8c674 100644 --- a/config/routes/tasks.rb +++ b/config/routes/tasks.rb @@ -340,7 +340,6 @@ get :index, as: 'index_dashboard_task' end - scope :view, controller: 'tasks/observation_matrices/view' do get '(:observation_matrix_id)', as: 'observation_matrix_view_task', action: :index end @@ -360,6 +359,10 @@ get 'index', as: 'index_row_coder_task' get 'set', as: 'set_row_coder_task' end + + scope :interactive_key, controller: 'tasks/observation_matrices/interactive_key' do + get '(:observation_matrix_id)', as: 'interactive_key_task', action: :index + end end scope :otus do diff --git a/db/migrate/20200716192152_add_descriptor_weight.rb b/db/migrate/20200716192152_add_descriptor_weight.rb new file mode 100644 index 0000000000..8ef402093a --- /dev/null +++ b/db/migrate/20200716192152_add_descriptor_weight.rb @@ -0,0 +1,6 @@ +class AddDescriptorWeight < ActiveRecord::Migration[6.0] + def change + add_column :descriptors, :weight, :integer + end +end + diff --git a/db/schema.rb b/db/schema.rb index a512cac2f7..8f2cfefd0e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_04_01_201911) do +ActiveRecord::Schema.define(version: 2020_07_16_192152) do # These are extensions that must be enabled in order to support this database enable_extension "fuzzystrmatch" @@ -557,6 +557,7 @@ t.string "default_unit" t.string "description_name" t.string "key_name" + t.integer "weight" t.index ["created_by_id"], name: "index_descriptors_on_created_by_id" t.index ["name"], name: "index_descriptors_on_name" t.index ["project_id"], name: "index_descriptors_on_project_id" diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb new file mode 100644 index 0000000000..1674ce603e --- /dev/null +++ b/lib/interactive_key.rb @@ -0,0 +1,690 @@ +# Contains methods used to build an interactive key +class InteractiveKey + + # required attribude to build the key + attr_accessor :observation_matrix_id + + #required attribute to build the key + attr_accessor :project_id + + #returns ObservationMatrix object + attr_accessor :observation_matrix + + #optional attribute to display the characters in a particular language + attr_accessor :language_id + + #optional attribute to provide a list of tagIDs to limit the set of characters "1|5|15" + attr_accessor :keyword_ids + + #optional attribute to provide a list of rowIDs to limit the set "1|5|10" + attr_accessor :row_filter + + + + #returns the list of Languages used as translations for descriptors + attr_accessor :descriptor_available_languages + + #returns the list of all descriptors for this matrix + attr_accessor :descriptors + + #returns the list of all Tags used with the descriptors + attr_accessor :descriptor_available_keywords + + #the validated Language object to display descriptors in a particular language + attr_accessor :language_to_use + + #list of descriptors reduced by keyword_ids + attr_accessor :descriptors_with_filter + + #list of rows to be included into the matrix + attr_accessor :rows_with_filter + + def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, keyword_ids: nil, row_filter: nil) + raise if observation_matrix_id.blank? || project_id.blank? + @observation_matrix_id = observation_matrix_id + @project_id = project_id + @observation_matrix = observation_matrix + @descriptor_available_languages = descriptor_available_languages + @language_id = language_id + @language_to_use = language_to_use + @keyword_ids = keyword_ids + @descriptor_available_keywords = descriptor_available_keywords + @descriptors_with_filter = descriptors_with_keywords + @row_filter = row_filter + @rows_with_filter = rows_with_filter + end + + def observation_matrix + ObservationMatrix.where(id: @observation_matrix_id, project_id: @project_id).first + end + + def descriptors + observation_matrix.descriptors.where('NOT descriptors.weight = 0 OR descriptors.weight IS NULL').order(:position) + end + + def descriptor_available_languages + descriptor_ids = descriptors.pluck(:id) + languages = Language.joins(:alternate_value_translations) + .where(alternate_values: {alternate_value_object_type: 'Descriptor', type: 'AlternateValue::Translation'}) + .where('alternate_values.alternate_value_object_id IN (?)', descriptor_ids ).order('languages.english_name').distinct.to_a + unless languages.empty? + languages = Language.where(english_name: 'English').to_a + languages + end + languages + end + + def language_to_use + return nil if @language_id.blank? + l = Language.where(id: @language_id).first + return nil if l.nil? || !descriptor_available_languages.to_a.include?(l) + l + end + + def descriptor_available_keywords + descriptor_ids = descriptors.pluck(:id) + tags = Keyword.joins(:tags) + .where(tags: {tag_object_type: 'Descriptor'}) + .where('tags.tag_object_id IN (?)', descriptor_ids ).order('name').distinct.to_a + end + + def descriptors_with_keywords + if @keyword_ids + descriptors.joins(:tags).where('tags.keyword_id IN (?)', @keyword_ids.to_s.split('|') ) + else + descriptors + end + end + + def rows + ObservationMatrixRow.where(observation_matrix_id: @observation_matrix_id) + end + + def rows_with_filter + if @row_item_filter + rows + else + rows.where('observation_matrix_rows.id IN (?)', @row_filter.to_s.split('|')) + end + + end + + def descriptor_import_predicate + ###TODO import_attribute 'char_weight' exclude characters with weight == 0 + end + + def observations + # id + # descriptor_id + # otu_id + # collection_object_id + # character_state_id + # continuous_value + # continuous_unit + # sample_min + # sample_max + # sample_unit + # presence + # description + # cached + # cached_column_label + # cached_row_label + # description + # type + ### types: Qualitative(char_states); Presence absence; Quantitative (single measurement); Sample (min, max); Free text + end + + # rst = All characters ordered by Characters.Weight DESC, Characters.Char, State.State" + # rst2 = List of all taxa from the key ordered by hiercode + # filter = taxa with specic IDs + # list of used states + # count the number of errors for each taxon +end + +=begin + + +' Save all used characters and their states into array charUsed() + +CharMax = 0 +Do Until rst.EOF + i = CStr(rst("Char")) + j = CStr(rst("State")) + r = replace(CStr(Request("a" & i)), " ", "") + r = replace(r, "aa", "a") + if (r = j and multistates = "") or (rst("Numeric") = True and r <> "" and isNumeric(left(r, inStr(r & "-", "-") - 1)) and isNumeric(right(r, len(r) - inStr(r, "-")))) then + charMax = charMax + 1 + charUsed(charMax, 1) = i + charUsed(charMax, 2) = r + charUsed(charMax, 3) = CStr(request("n" & i)) + if charUsed(charMax, 3) = "1" then + states = states & "-" & rst("Key2") + else + states = states & rst("Key2") + end if + if rst("Numeric") = True then + states = states & "-" & r & "b" + else + states = states & "b" + end if + where2 = where2 & " OR Char=" & i + elseif multistates = "1" and rst("Numeric") = False then + m = CStr(Request("m" & i)) + if (inStr(m, "!") = 0 and inStr(m, "a" & j & "a") > 0) or (m = "" and r = j) or (inStr(m, "!") = 1 and ((inStr(m, "a" & j & "a") > 0 and inStr(m, "a" & r & "a") > 0) or (r = j and inStr(m, "a" & r & "a") = 0))) then + if charUsed(charMax, 1) <> i then charMax = charMax + 1 + charUsed(charMax, 1) = i + charUsed(charMax, 2) = charUsed(charMax, 2) & "a" & j & "a" + charUsed(charMax, 3) = CStr(request("n" & i)) + if charUsed(charMax, 3) = "1" then + states = states & "-" & rst("Key2") & "b" + else + states = states & rst("Key2") & "b" + end if + where2 = where2 & " OR Char=" & i + end if + end if + rst.moveNext +Loop +rst.MoveFirst +if where2 & "" <> "" then where2 = "AND (" & right(where2, len(where2) - 4) & ") " + +' Open recordset Matrix of characters + +if keyN <> "" then where1 = "AND ','&CharTableTotal.KeyN&',' Like '%," & keyN & ",%' AND ','&CharTableTotal.CharKeyN&',' Like '%," & keyN & ",%' " +strSQL = "SELECT Morph, Char, State, Hiercode, Numeric, NumericFrom, NumericTo FROM CharTableTotal " +if cat = "1" then + strSQL = strSQL & replace(where, "Characters", "CharTableTotal") & where1 & where2 & "ORDER BY Morph, Weight DESC, Char, Hiercode, State" +else + strSQL = strSQL & replace(where, "Characters", "CharTableTotal") & where1 & where2 & "ORDER BY Weight DESC, Char, Hiercode, State" +end if +rst2.Open strSQL, Conn + + +if rst2.eof then ' Datamatrix is empty + response.write "

The datamatrix is empty!

" +else + +' Mark the taxa in array taxa() which does not fit to criteria (count number of errors) + +for j = 1 to charMax + for i = 1 to taxaMax + if taxa(i, 2) <> "-1" then + do until left(rst2("Hiercode"), len(taxa(i, 1))) = taxa(i, 1) and rst2("Char") & "" = charUsed(j, 1) + rst2.MoveNext + loop + if multistates = "1" and rst2("Numeric") = False then + if charUsed(j, 3) = "1" then ' character with not + do until inStr(charUsed(j, 2), rst2("State")) = 0 or (rst2("State") & "" = "" and unknowns <> "1") or left(rst2("Hiercode"), len(taxa(i, 1))) <> taxa(i, 1) + rst2.MoveNext + if rst2.EOF then exit do + loop + else + do until inStr(charUsed(j, 2), rst2("State")) > 0 or (rst2("State") & "" = "" and unknowns <> "1") or left(rst2("Hiercode"), len(taxa(i, 1))) <> taxa(i, 1) + rst2.MoveNext + if rst2.EOF then exit do + loop + end if + else + if charUsed(j, 3) = "1" then ' character with not + do until (rst2("Numeric") = True and (rst2("NumericFrom") > cDbl(right(charUsed(j, 2), len(charUsed(j, 2)) - inStr(charUsed(j, 2), "-"))) or rst2("NumericTo") < cDbl(left(charUsed(j, 2), inStr(charUsed(j, 2) & "-", "-")-1)))) or (charUsed(j, 2) <> rst2("State") & "" and rst2("Numeric") = False) or (rst2("State") & "" = "" and unknowns <> "1") or left(rst2("Hiercode"), len(taxa(i, 1))) <> taxa(i, 1) + rst2.MoveNext + if rst2.EOF then exit do + loop + else + do until (rst2("Numeric") = True and rst2("NumericFrom") <= cDbl(right(charUsed(j, 2), len(charUsed(j, 2)) - inStr(charUsed(j, 2), "-"))) and rst2("NumericTo") >= cDbl(left(charUsed(j, 2), inStr(charUsed(j, 2) & "-", "-")-1))) or (charUsed(j, 2) = rst2("State") & "" and rst2("Numeric") = False) or (rst2("State") & "" = "" and unknowns <> "1") or left(rst2("Hiercode"), len(taxa(i, 1))) <> taxa(i, 1) + rst2.MoveNext + if rst2.EOF then exit do + loop + end if + end if + if rst2.EOF then + taxa(i, 2) = taxa(i, 2) + 1 + elseIf left(rst2("Hiercode"), len(taxa(i, 1))) <> taxa(i, 1) then + taxa(i, 2) = taxa(i, 2) + 1 + end if + end if + next +next + +' Making query strings for lists of taxa + +for t = 1 to taxaMax + if CInt(taxa(t, 2)) <= tol and taxa(t, 2) <> "-1" then + queryStr1 = queryStr1 & taxa(t, 0) & "a" & taxa(t, 2) & "a" + if CInt(taxa(t, 2)) < tol then taxaRemTol = taxaRemTol + 1 + taxaRem = taxaRem + 1 + else + queryStr2 = queryStr2 & taxa(t, 0) & "a" & taxa(t, 2) & "a" + end if +next +if len(queryStr1) > 0 then queryStr1 = states & left(queryStr1, len(queryStr1) - 1) +if len(queryStr2) > 0 then queryStr2 = states & left(queryStr2, len(queryStr2) - 1) + +' Resort recordset rst2 + +rst2.Close +strSQL = "SELECT Morph, Char, State, Hiercode, Numeric, NumericFrom, NumericTo " &_ + "FROM CharTableTotal " +if cat = "1" then + strSQL = strSQL & replace(where, "Characters", "CharTableTotal") & where1 & "ORDER BY Morph, Weight DESC, Char, State, Hiercode" +else + strSQL = strSQL & replace(where, "Characters", "CharTableTotal") & where1 & "ORDER BY Weight DESC, Char, State, Hiercode" +end if +rst2.Open strSQL, Conn + +' Make the form with set of character + +a = 1 +t = 1 +m = "" +j = rst("Char") & "" +Do Until rst.EOF + if rank <> "" then + for i = 1 to taxaMax + taxa(i, 3) = "0" + next + end if + i = rst("Char") & "" + morphN = rst("Morph") + charName = charReplace(rst("Char" & lng)) + + descr = rst("Descr" & lng) & "" + + if not rst2.eof then + Do Until rst2("Char") & "" = i + rst2.MoveNext + if rst2.EOF then exit do + Loop + end if + + if not rst2.eof then + fig = 0 + weight = rst("Weight") & "" + CharTemp1 = "" + if weight <> "" then weight = ", I=" & weight + usefull = 0 + stUnknown = 0 + stNum = 0 + stSum = 0 + numMin = 9999999 + numMax = -9999999 + + if rst("Numeric") = False then ' !!!!!!!!!!Not Numeric!!!!!!!!! + if multistates = "1" then + m = request("m" & i) & "" + if (inStr(m, "!") = 1 and inStr(m, "a" & Request("a" & i) & "a") > 0) or (m <> "" and inStr(m, "!") <> 1) then + m = Replace("", "'!'", "''") & sp + else + m = "" & sp + end if + end if + if charUsed(a, 1) & "" <> i then + CharTemp = "
  • " & charName & " (" & UCase(rst("Type")) & weight & ")
    " & sp & m & "not   " & sp & sp + If fig = 1 or descr <> "" or multistates = "1" then + opt = len(CharTemp) - len(replace(CharTemp, "option", "")) + if fig = 1 and multistates = "1" then opt = opt + 12 + if opt > 90 and fig = 1 then + CharTemp = replace(CharTemp, ">" & charName & "<", ">" & charName & "<") + elseIf opt > 50 or (multistates = "1" and fig = 1) then + CharTemp = replace(CharTemp, ">" & charName & "<", ">" & charName & "<") + elseIf opt < 50 then + CharTemp = replace(CharTemp, ">" & charName & "<", ">" & charName & "<") + end if + end if + + else ' !!!!!!!Numeric!!!!!!!! + + if not rst2.eof then + hc = 0 + Do Until rst2("Char") & "" <> i or rst2("State") & "" <> "" + z = 0 + Do Until left(rst2("Hiercode"), len(taxa(t, 1))) = taxa(t, 1) + t = t + 1 + if t > taxaMax then + t = 1 + z = z + 1 + if z > 1 then exit do + end if + Loop + if CInt(taxa(t, 2)) = tol and hc <> taxa(t, 1) and z < 2 then + if rank <> "" then taxa(t, 3) = "1" + stUnknown = stUnknown + 1 + hc = taxa(t, 1) + end if + rst2.MoveNext + if rst2.eof then exit do + Loop + end if + + usefull = 0 + if not rst2.eof then + stCount = 0 + hc = 0 + do until rst2("Char") & "" <> i + z = 0 + Do Until left(rst2("Hiercode"), len(taxa(t, 1))) = taxa(t, 1) + t = t + 1 + if t > taxaMax then + t = 1 + z = z + 1 + if z > 1 then exit Do + end if + Loop + if CInt(taxa(t, 2)) = tol and z < 2 then + if hc <> taxa(t, 1) and taxa(t, 3) <> "1" then + hc = taxa(t, 1) + stNum = stNum + 1 + strCharArr(stNum, 0) = rst2("NumericTo") + strCharArr(stNum, 4) = rst2("NumericFrom") + end if + if strCharArr(stNum, 0) > rst2("NumericTo") then strCharArr(stNum, 0) = rst2("NumericTo") + if strCharArr(stNum, 4) < rst2("NumericFrom") then strCharArr(stNum, 4) = rst2("NumericFrom") + if numMin > rst2("NumericFrom") then + if numMin < 9999999 then usefull = 1 + numMin = rst2("NumericFrom") + end if + if numMax < rst2("NumericTo") then + if numMax > -9999999 then usefull = 1 + numMax = rst2("NumericTo") + end if + stCount = 1 + end if + rst2.moveNext + if rst2.eof then exit do + loop + end if + if charUsed(a, 1) & "" <> i then + if numMin = 9999999 then + charTemp1 = "" + elseIf numMin = numMax then + charTemp1 = numMin & " " + else + CharTemp1 = numMin & "-" & numMax & " " + end if + CharTemp = "
  • " & charName & " [" & charTemp1 & charReplace(rst("State" & lng)) & "] (" & UCase(rst("Type")) & weight & ")
    " & sp & "not  " & sp + else + CharTemp = "
  • " & charName & " [" & charReplace(rst("State" & lng)) & "] (" & UCase(rst("Type")) & weight & ")
    " & sp & "not  " & sp + end if + If rst("fig") & "" <> "" or descr <> "" then + CharTemp = replace(CharTemp, ">" & charName & " [" & charTemp1 & charReplace(rst("State" & lng)) & "]<", ">" & charName & " [" & charTemp1 & charReplace(rst("State" & lng)) & "]<") + end if + + rst.MoveNext + if not rst.EOF then j = rst("Char") & "" + + end if ' !!!!!!!!!Numeric!!!!!!!!!! + end if + + if charUsed(a, 1) = i then + strChar2 = strChar2 + CharTemp + a = a + 1 + ElseIf usefull = 0 then + strChar3 = strChar3 & CharTemp + Else + if taxaRem > 1 then + if cat = "1" and rst1("Morph") <> morphN then + Do until rst1("Morph") = morphN + rst1.moveNext + Loop + morph = 0 + end if + if cat = "1" and rst1("Morph") = morphN and morph <> 1 then + l = Replace(rst1("Morph" & lng), " ", " ") + strChar1 = strChar1 & "

    " & l & "

    " & sp & sp + link = link & "" & l & " | " & sp + morph = 1 + end if + if cat <> "1" then + if numMin = 9999999 then stMed = taxaRem / stNum else stMed = taxaRem + For i1 = 1 to stNum + if numMin = 9999999 then + stSum = stSum + ((stMed) - strCharArr(i1, 0)) ^ 2 + else + strCharArr(i1, 0) = strCharArr(i1, 4) - strCharArr(i1, 0) + if strCharArr(i1, 0) = 0 then strCharArr(i1, 0) = (numMax - numMin) / 10 + stSum = stSum + strCharArr(i1, 0) + end if + Next + strCharMax = strCharMax + 1 + if numMax = numMin then numMax = numMax + 0.00001 + if numMin = 9999999 then + strCharArr(strCharMax, 2) = stMed + Sqr(stSum) + else + strCharArr(strCharMax, 2) = stMed * (stSum / stNum / (numMax - numMin)) * (2 - stNum / taxaRem) + end if + strCharArr(strCharMax, 1) = CharTemp ' & strCharArr(strCharMax, 2) '!!!!!!!!!!!!!!!! + strCharArr(strCharMax, 3) = CLng("0" & replace(weight, ", I=", "")) + else + strChar1 = strChar1 & CharTemp + end if + else + strChar3 = strChar3 & CharTemp + End if + End if +Loop + +' Outputtin form + +%> + + + +<% + +if len(link) > 9 then + link = left(link, len(link)-9) +end if %> + +
    + + + + + + + + + + + + + + +<% +if cat <> "1" and strCharMax > 1 then +For i = 1 to strCharMax - 1 +For j = i + 1 to strCharMax +if strCharArr(i, 3) > strCharArr(j, 3) and cat = "0" then exit for + if strCharArr(i, 2) > strCharArr(j, 2) then + CharTemp = strCharArr(i, 1) + strCharArr(i, 1) = strCharArr(j, 1) + strCharArr(j, 1) = CharTemp + CharTemp = strCharArr(i, 2) + strCharArr(i, 2) = strCharArr(j, 2) + strCharArr(j, 2) = CharTemp + end if + Next + strChar1 = strChar1 + strCharArr(i, 1) + Next + strChar1 = strChar1 + strCharArr(strCharMax, 1) + elseIf cat = "2" or strCharMax = 1 then + strChar1 = strChar1 + strCharArr(1, 1) + end if + if strChar2 & "" <> "" or filter <> "" then + response.write "
      " & sp + if strChar1 & "" <> "" then + response.write "
    • " & rst3("Useful") & "" & sp + if len(link) > 0 then + response.write "
      " & sp & "(" & link & ")" & sp & sp + end if + end if + if strChar3 & "" <> "" and char = "1" then + response.write "
    • " & rst3("Relevant") & "" & sp + end if + response.write "
    " & sp & sp + end if + + + if strChar2 & "" <> "" then + response.Write sp & "" & sp & "

    " & rst3("Used") & "

    " & sp & sp + end if + if filter <> "" then + if strChar2 & "" = "" then response.Write sp & "" & sp & "

    " & rst3("Used") & "

    " & sp & sp + response.write "

     Filter

    " & sp & sp + else + response.write "" & sp & sp + end if + if strChar2 & "" <> "" then + response.write "
      " & sp & sp & strChar2 & "
    " & sp + end if + if strChar1 & "" <> "" then + response.Write sp & "" & sp & "

    " & rst3("Useful") & "

    " & sp & sp & "

    " & sp & link & sp & "

    " & sp & sp & "
      " & sp & sp & strChar1 & "
    " & sp + end if + if strChar3 & "" <> "" and char = "1" then + response.Write sp & "" & sp & "

    " & rst3("Relevant") & "

    " & sp & sp & "
      " & sp & sp & strChar3 & "
    " & sp + end if + + + function charReplace(string) + Do + if inStr(string, "[") > 0 and inStr(string, "]") - inStr(string, "[") > 0 then + string = trim(left(string, inStr(string, "[")-1) & right(string, len(string) - inStr(string, "]"))) + else + Exit Do + end if + Loop + string = replace(string & "", "{", "") + string = replace(string, "}", "") + string = replace(string, " & ", " & ") + if inStr(string & "<", "<") < inStrRev(">" & string, ">") and inStr(string, " 0 then + else + string = replace(string, "<", "<") + string = replace(string, ">", ">") + end if + charReplace = string + end function + +rst3.Close +Set rst3 = Nothing + +end if ' Datamatrix is empty +=end diff --git a/spec/lib/interactive_key_spec.rb b/spec/lib/interactive_key_spec.rb new file mode 100644 index 0000000000..6c9ab6d5d5 --- /dev/null +++ b/spec/lib/interactive_key_spec.rb @@ -0,0 +1,86 @@ +require 'rails_helper' +require 'interactive_key' + +describe InteractiveKey, type: :model, group: :observation_matrix do + + context 'respond to' do + let(:observation_matrix) { ObservationMatrix.create!(name: 'Matrix') } + let(:otu1) { Otu.create!(name: 'phoo') } + let(:otu2) { Otu.create!(name: 'barr') } + let(:descriptor1) { Descriptor::Working.create!(name: 'working1') } + let(:descriptor2) { Descriptor::Working.create!(name: 'working2') } + let!(:rus) { FactoryBot.create(:russian) } + let!(:eng) { FactoryBot.create(:english) } + + let(:interactive_key) { InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id) } + +# observation_matrix.observation_matrix_row_items << ObservationMatrixRowItem::SingleOtu.new(otu: otu1) +# observation_matrix.observation_matrix_row_items << ObservationMatrixRowItem::SingleOtu.new(otu: otu2) +# observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor1) +# observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor2) + + specify 'observation_matrix' do + expect(interactive_key.observation_matrix).to eq(observation_matrix) + end + + specify 'descriptor_available_languages' do + eng + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor1) + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor2) + a = AlternateValue.create(type: 'AlternateValue::Translation', value: 'zzz', alternate_value_object: descriptor1, alternate_value_object_attribute: 'name', language_id: rus.id) + expect(interactive_key.descriptor_available_languages.count).to eq(2) + end + + specify 'language_to_use' do + eng + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor1) + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor2) + a = AlternateValue.create(type: 'AlternateValue::Translation', value: 'zzz', alternate_value_object: descriptor1, alternate_value_object_attribute: 'name', language_id: rus.id) + interactive_key = InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id, language_id: rus.id) + expect(interactive_key.language_to_use).to eq(rus) + end + + specify 'descriptor_available_keywords' do + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor1) + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor2) + k = Keyword.create(name: 'zzz', definition: 'zzzzzzzzzzzzzzzzzzzzzzzzz') + descriptor1.tags.create(keyword: k) + expect(interactive_key.descriptor_available_keywords.count).to eq(1) + end + + specify 'descriptor_weight' do + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor1) + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor2) + interactive_key = InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id) + expect(interactive_key.descriptors_with_filter.count).to eq(2) + descriptor1.weight = 0 + descriptor1.save + interactive_key = InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id) + expect(interactive_key.descriptors_with_filter.count).to eq(1) + end + + specify 'descriptors_with_keywords' do + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor1) + observation_matrix.observation_matrix_column_items << ObservationMatrixColumnItem::SingleDescriptor.new(descriptor: descriptor2) + k1 = Keyword.create(name: 'zzz1', definition: 'zzzzzzzzzzzzzzzzzzzzzzzzz') + k2 = Keyword.create(name: 'zzz2', definition: 'zzzzzzzzzzzzzzzzzzzzzzzzzz') + t1 = descriptor1.tags.create(keyword: k1) + t2 = descriptor2.tags.create(keyword: k2) + interactive_key = InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id, keyword_ids: t1.id) + expect(interactive_key.descriptors_with_filter.count).to eq(1) + interactive_key = InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id, keyword_ids: t1.id.to_s + '|' + t2.id.to_s) + expect(interactive_key.descriptors_with_filter.count).to eq(2) + end + + specify 'rows_with_filter' do + o1 = observation_matrix.observation_matrix_row_items << ObservationMatrixRowItem::SingleOtu.new(otu: otu1) + o2 = observation_matrix.observation_matrix_row_items << ObservationMatrixRowItem::SingleOtu.new(otu: otu2) + interactive_key = InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id, row_filter: observation_matrix.observation_matrix_rows.first.id) + expect(interactive_key.rows_with_filter.count).to eq(1) + interactive_key = InteractiveKey.new(observation_matrix_id: observation_matrix.id, project_id: observation_matrix.project_id, row_filter: observation_matrix.observation_matrix_rows.first.id.to_s + '|' + observation_matrix.observation_matrix_rows.last.id.to_s) + expect(interactive_key.rows_with_filter.count).to eq(2) + end + + + end +end From 7276636b552cc2b99d623730c48b2b735927bc2e Mon Sep 17 00:00:00 2001 From: jrflood Date: Tue, 4 Aug 2020 11:47:39 -0500 Subject: [PATCH 002/189] Code cloning for #1511 --- app/controllers/sources_controller.rb | 21 +++++++++++++++++---- config/routes/api_v1.rb | 4 ++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb index b9d7b6ad12..a1141cb535 100644 --- a/app/controllers/sources_controller.rb +++ b/app/controllers/sources_controller.rb @@ -22,6 +22,19 @@ def index end end + # GET /api/v1/sources + def api_index + @sources = + Queries::Source::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + render '/sources/api/index.json.jbuilder' + end + + # GET /api/v1/sources/:id + def api_show + @taxon_name = Source.where(project_id: sessions_current_project_id).find(params[:id]) + render '/sources/api/show.json.jbuilder' + end + def list @sources = Source.page(params[:page]) end @@ -53,7 +66,7 @@ def new # POST /sources # POST /sources.json def create - @source = new_source + @source = new_source respond_to do |format| if @source&.save format.html { redirect_to url_for(@source.metamorphosize), @@ -198,10 +211,10 @@ def download end # GET /sources/generate.json? - def generate + def generate sources = Queries::Source::Filter.new(filter_params).all.page(params[:page]).per(params[:per] || 2000) @download = ::Export::Bibtex.download(sources, request.url, is_public: (params[:is_public] == 'true' ? true : false)) - render '/downloads/show' + render '/downloads/show' end private @@ -234,7 +247,7 @@ def filter_params :per, :project_id, :query_term, - :recent, + :recent, :roles, :source_type, :tags, diff --git a/config/routes/api_v1.rb b/config/routes/api_v1.rb index ee216bcca1..de1f777c8a 100644 --- a/config/routes/api_v1.rb +++ b/config/routes/api_v1.rb @@ -35,6 +35,10 @@ get '/taxon_names/autocomplete', to: '/taxon_names#autocomplete' get '/taxon_names/:id', to: '/taxon_names#api_show' + get '/sources', to: '/sources#api_index' + get '/sources/:id', to: '/sources#api_show' + get '/sources/autocomplete', to: '/sources#autocomplete' + end # Authenticate membership at the data controller level From a6113988f7f280ced1f522e84a03c11617a4b001 Mon Sep 17 00:00:00 2001 From: jrflood Date: Wed, 5 Aug 2020 15:03:28 -0500 Subject: [PATCH 003/189] Code cloning for #1509 #1510 #1511 a la taxon_names --- app/controllers/identifiers_controller.rb | 15 ++++++++++++++- app/controllers/people_controller.rb | 19 ++++++++++++++++--- app/controllers/sources_controller.rb | 2 +- config/routes/api_v1.rb | 8 ++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/app/controllers/identifiers_controller.rb b/app/controllers/identifiers_controller.rb index a1a93b5c05..fe6ff5969e 100644 --- a/app/controllers/identifiers_controller.rb +++ b/app/controllers/identifiers_controller.rb @@ -18,6 +18,19 @@ def index end end + # GET /api/v1/identifiers + def api_index + @identifiers = + Queries::Identifier::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + render '/identifiers/api/index.json.jbuilder' + end + + # GET /api/v1/identifiers/:id + def api_show + @identifiers = Identifier.where(project_id: sessions_current_project_id).find(params[:id]) + render '/identifiers/api/show.json.jbuilder' + end + # GET /identifers/1 def show end @@ -115,7 +128,7 @@ def identifier_params end def autocomplete_params - params.permit(identifier_object_types: []).to_h.symbolize_keys.merge(project_id: sessions_current_project_id) # :exact + params.permit(identifier_object_types: []).to_h.symbolize_keys.merge(project_id: sessions_current_project_id) # :exact end end diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 2a3595a41a..1c5596e4c0 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -2,7 +2,7 @@ class PeopleController < ApplicationController include DataControllerConfiguration::SharedDataControllerConfiguration before_action :set_person, only: [:show, :edit, :update, :destroy, :roles, :similar] - after_action -> { set_pagination_headers(:people) }, only: [:index], if: :json_request? + after_action -> { set_pagination_headers(:people) }, only: [:index], if: :json_request? # GET /people # GET /people.json @@ -14,11 +14,24 @@ def index render '/shared/data/all/index' } format.json { - @people = Queries::Person::Filter.new(filter_params).all.order(:cached).page(params[:page]).per(params[:per]) + @people = Queries::Person::Filter.new(filter_params).all.order(:cached).page(params[:page]).per(params[:per]) } end end + # GET /api/v1/people + def api_index + @people = + Queries::Person::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + render '/people/api/index.json.jbuilder' + end + + # GET /api/v1/people/:id + def api_show + @taxon_name = Person.where(project_id: sessions_current_project_id).find(params[:id]) + render '/people/api/show.json.jbuilder' + end + # GET /people/1 # GET /people/1.json def show @@ -50,7 +63,7 @@ def create end def similar - @people = Queries::Person::Filter.new(last_name: @person.last_name, first_name: @person.first_name, levenshtein_cuttoff: 3).levenshtein_similar.order(:last_name, :first_name) + @people = Queries::Person::Filter.new(last_name: @person.last_name, first_name: @person.first_name, levenshtein_cuttoff: 3).levenshtein_similar.order(:last_name, :first_name) render '/people/index' end diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb index a1141cb535..65e36607d8 100644 --- a/app/controllers/sources_controller.rb +++ b/app/controllers/sources_controller.rb @@ -31,7 +31,7 @@ def api_index # GET /api/v1/sources/:id def api_show - @taxon_name = Source.where(project_id: sessions_current_project_id).find(params[:id]) + @sources = Source.where(project_id: sessions_current_project_id).find(params[:id]) render '/sources/api/show.json.jbuilder' end diff --git a/config/routes/api_v1.rb b/config/routes/api_v1.rb index de1f777c8a..8bb29fe7b2 100644 --- a/config/routes/api_v1.rb +++ b/config/routes/api_v1.rb @@ -35,10 +35,18 @@ get '/taxon_names/autocomplete', to: '/taxon_names#autocomplete' get '/taxon_names/:id', to: '/taxon_names#api_show' + get '/identifiers', to: '/identifiers#api_index' + get '/identifiers/:id', to: '/identifiers#api_show' + get '/identifiers/autocomplete', to: '/identifiers#autocomplete' + get '/sources', to: '/sources#api_index' get '/sources/:id', to: '/sources#api_show' get '/sources/autocomplete', to: '/sources#autocomplete' + get '/people', to: '/people#api_index' + get '/people/:id', to: '/people#api_show' + get '/people/autocomplete', to: '/people#autocomplete' + end # Authenticate membership at the data controller level From 9c6202fddadea20f6d80859ac94dad8926656c75 Mon Sep 17 00:00:00 2001 From: jrflood Date: Thu, 6 Aug 2020 01:09:34 -0500 Subject: [PATCH 004/189] Code cloning for #1509 #1510 #1511 a la taxon_names --- app/controllers/identifiers_controller.rb | 2 +- config/routes/api_v1.rb | 16 +-- package-lock.json | 162 +++++++++++----------- 3 files changed, 90 insertions(+), 90 deletions(-) diff --git a/app/controllers/identifiers_controller.rb b/app/controllers/identifiers_controller.rb index fe6ff5969e..4f57424bb2 100644 --- a/app/controllers/identifiers_controller.rb +++ b/app/controllers/identifiers_controller.rb @@ -21,7 +21,7 @@ def index # GET /api/v1/identifiers def api_index @identifiers = - Queries::Identifier::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + Queries::Identifier::Filter.new(identifier_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) render '/identifiers/api/index.json.jbuilder' end diff --git a/config/routes/api_v1.rb b/config/routes/api_v1.rb index 8bb29fe7b2..b1e47a7e26 100644 --- a/config/routes/api_v1.rb +++ b/config/routes/api_v1.rb @@ -8,6 +8,14 @@ get :ping, controller: 'ping' get :pingz, controller: 'ping' + get '/sources', to: '/sources#api_index' + get '/sources/:id', to: '/sources#api_show' + get '/sources/autocomplete', to: '/sources#autocomplete' + + get '/people', to: '/people#api_index' + get '/people/:id', to: '/people#api_show' + get '/people/autocomplete', to: '/people#autocomplete' + # authenticated by user_token defaults authenticate_user: true do get '/user_authenticated', to: 'base#index' @@ -39,14 +47,6 @@ get '/identifiers/:id', to: '/identifiers#api_show' get '/identifiers/autocomplete', to: '/identifiers#autocomplete' - get '/sources', to: '/sources#api_index' - get '/sources/:id', to: '/sources#api_show' - get '/sources/autocomplete', to: '/sources#autocomplete' - - get '/people', to: '/people#api_index' - get '/people/:id', to: '/people#api_show' - get '/people/autocomplete', to: '/people#autocomplete' - end # Authenticate membership at the data controller level diff --git a/package-lock.json b/package-lock.json index 7f7a28e415..2abcbdd56a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1319,7 +1319,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { "version": "1.3.7", @@ -1491,12 +1491,12 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "are-we-there-yet": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha1-SzXClE8GKov82mZBB2A1D+nd/CE=", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -1505,7 +1505,7 @@ "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "requires": { "sprintf-js": "~1.0.2" } @@ -1524,7 +1524,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "arr-union": { "version": "3.1.0", @@ -1594,7 +1594,7 @@ "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", @@ -2230,7 +2230,7 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, "balanced-match": { @@ -2241,7 +2241,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -2263,7 +2263,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "requires": { "kind-of": "^6.0.0" } @@ -2271,7 +2271,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "requires": { "kind-of": "^6.0.0" } @@ -2279,7 +2279,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -2414,7 +2414,7 @@ "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2423,7 +2423,7 @@ "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -2455,7 +2455,7 @@ "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -2468,7 +2468,7 @@ "browserify-cipher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "requires": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", @@ -2538,7 +2538,7 @@ "browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "requires": { "pako": "~1.0.5" } @@ -2619,7 +2619,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -2784,7 +2784,7 @@ "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -2793,7 +2793,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -3091,7 +3091,7 @@ "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -3173,7 +3173,7 @@ "copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", "requires": { "aproba": "^1.1.1", "fs-write-stream-atomic": "^1.0.8", @@ -3229,7 +3229,7 @@ "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "requires": { "bn.js": "^4.1.0", "elliptic": "^6.0.0" @@ -3245,7 +3245,7 @@ "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -3257,7 +3257,7 @@ "create-hmac": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "requires": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -3295,7 +3295,7 @@ "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "requires": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", @@ -3706,7 +3706,7 @@ "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -3715,7 +3715,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "requires": { "kind-of": "^6.0.0" } @@ -3723,7 +3723,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "requires": { "kind-of": "^6.0.0" } @@ -3731,7 +3731,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -3808,7 +3808,7 @@ "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "requires": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", @@ -3875,7 +3875,7 @@ "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=" + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, "domelementtype": { "version": "1.3.1", @@ -4026,7 +4026,7 @@ "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "requires": { "prr": "~1.0.1" } @@ -4623,7 +4623,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "requires": { "estraverse": "^4.1.0" } @@ -4667,7 +4667,7 @@ "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -4857,7 +4857,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "requires": { "is-plain-object": "^2.0.4" } @@ -4867,7 +4867,7 @@ "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -4898,7 +4898,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "requires": { "kind-of": "^6.0.0" } @@ -4906,7 +4906,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "requires": { "kind-of": "^6.0.0" } @@ -4914,7 +4914,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -5230,7 +5230,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -5256,7 +5256,7 @@ "gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", "requires": { "globule": "^1.0.0" } @@ -5807,7 +5807,7 @@ "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "requires": { "loose-envify": "^1.0.0" } @@ -5876,7 +5876,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { "version": "1.2.0", @@ -5922,7 +5922,7 @@ "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -5932,7 +5932,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -6027,7 +6027,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "requires": { "isobject": "^3.0.1" } @@ -6043,7 +6043,7 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=" + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" }, "is-stream": { "version": "1.1.0", @@ -6086,7 +6086,7 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "is-wsl": { "version": "1.1.0", @@ -6169,7 +6169,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=" + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-schema": { "version": "0.2.3", @@ -6579,7 +6579,7 @@ "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -6599,7 +6599,7 @@ "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" @@ -6657,7 +6657,7 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "minimalistic-crypto-utils": { "version": "1.0.1", @@ -6667,7 +6667,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" } @@ -7017,7 +7017,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -7242,7 +7242,7 @@ "osenv": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha1-hc36+uso6Gd/QW4odZK18/SepBA=", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" @@ -7368,7 +7368,7 @@ "path-complete-extname": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/path-complete-extname/-/path-complete-extname-1.0.0.tgz", - "integrity": "sha1-+ImYXckQAMgVUVwL/tBsWs2gdSs=" + "integrity": "sha512-CVjiWcMRdGU8ubs08YQVzhutOR5DEfO97ipRIlOGMK5Bek5nQySknBpuxVAVJ36hseTNs+vdIcv57ZrWxH7zvg==" }, "path-dirname": { "version": "1.0.2", @@ -8538,7 +8538,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=" + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process": { "version": "0.11.10", @@ -8618,7 +8618,7 @@ "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "requires": { "duplexify": "^3.6.0", "inherits": "^2.0.3", @@ -8639,7 +8639,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "q": { "version": "1.5.1", @@ -8692,7 +8692,7 @@ "randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "requires": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" @@ -8897,7 +8897,7 @@ "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -9153,7 +9153,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=" + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "retry": { "version": "0.12.0", @@ -9206,7 +9206,7 @@ "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -9223,7 +9223,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -9236,7 +9236,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass-graph": { "version": "2.2.5", @@ -9271,7 +9271,7 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "schema-utils": { "version": "2.7.0", @@ -9481,7 +9481,7 @@ "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -9550,7 +9550,7 @@ "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -9596,7 +9596,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -9614,7 +9614,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "requires": { "kind-of": "^6.0.0" } @@ -9622,7 +9622,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "requires": { "kind-of": "^6.0.0" } @@ -9630,7 +9630,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -9642,7 +9642,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "requires": { "kind-of": "^3.2.0" }, @@ -9834,7 +9834,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "requires": { "extend-shallow": "^3.0.0" } @@ -9928,7 +9928,7 @@ "stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "requires": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.1", @@ -9998,7 +9998,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" } @@ -10136,7 +10136,7 @@ "stylus-loader": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", - "integrity": "sha1-J6cGQgsFo44DjnyssVNXjUUFE8Y=", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", "dev": true, "requires": { "loader-utils": "^1.0.2", @@ -10433,7 +10433,7 @@ "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -10687,7 +10687,7 @@ "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "requires": { "punycode": "^2.1.0" } @@ -11483,7 +11483,7 @@ "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "requires": { "isexe": "^2.0.0" } @@ -11496,7 +11496,7 @@ "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" } From 79d0e1b7d26ea998afdebe31627453a5ea3d808a Mon Sep 17 00:00:00 2001 From: jrflood Date: Thu, 6 Aug 2020 12:15:27 -0500 Subject: [PATCH 005/189] DE-Failed api index and show #1510 #1511 using .// vs .//api --- app/controllers/identifiers_controller.rb | 3 +-- app/controllers/people_controller.rb | 9 ++++----- app/controllers/sources_controller.rb | 9 ++++----- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/app/controllers/identifiers_controller.rb b/app/controllers/identifiers_controller.rb index 4f57424bb2..24beeda242 100644 --- a/app/controllers/identifiers_controller.rb +++ b/app/controllers/identifiers_controller.rb @@ -20,8 +20,7 @@ def index # GET /api/v1/identifiers def api_index - @identifiers = - Queries::Identifier::Filter.new(identifier_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + @identifiers = Queries::Identifier::Filter.new(identifier_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) render '/identifiers/api/index.json.jbuilder' end diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 1c5596e4c0..d318d6e399 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -21,15 +21,14 @@ def index # GET /api/v1/people def api_index - @people = - Queries::Person::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) - render '/people/api/index.json.jbuilder' + @people = Queries::Person::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + render '/people/index.json.jbuilder'######/people/api/index.json.jbuilder' end # GET /api/v1/people/:id def api_show - @taxon_name = Person.where(project_id: sessions_current_project_id).find(params[:id]) - render '/people/api/show.json.jbuilder' + @person = Person.find(params[:id]) + render '/people/show.json.jbuilder'########/people/api/show.json.jbuilder' end # GET /people/1 diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb index 65e36607d8..c46fc2e9db 100644 --- a/app/controllers/sources_controller.rb +++ b/app/controllers/sources_controller.rb @@ -24,15 +24,14 @@ def index # GET /api/v1/sources def api_index - @sources = - Queries::Source::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) - render '/sources/api/index.json.jbuilder' + @sources = Queries::Source::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + render '/sources/index.json.jbuilder'#####/sources/api/index.json.jbuilder end # GET /api/v1/sources/:id def api_show - @sources = Source.where(project_id: sessions_current_project_id).find(params[:id]) - render '/sources/api/show.json.jbuilder' + @source = Source.find(params[:id]) + render '/sources/show.json.jbuilder'######/sources/api/show.json.jbuilder end def list From 8b109ad1f5db9be76c8bf3f5a5d54144f719ec70 Mon Sep 17 00:00:00 2001 From: jrflood Date: Fri, 7 Aug 2020 10:28:41 -0500 Subject: [PATCH 006/189] checkpoint identifiers WIP --- app/controllers/identifiers_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/identifiers_controller.rb b/app/controllers/identifiers_controller.rb index 24beeda242..c4c1a02225 100644 --- a/app/controllers/identifiers_controller.rb +++ b/app/controllers/identifiers_controller.rb @@ -21,13 +21,13 @@ def index # GET /api/v1/identifiers def api_index @identifiers = Queries::Identifier::Filter.new(identifier_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) - render '/identifiers/api/index.json.jbuilder' + render '/identifiers/index.json.jbuilder'#######/identifiers/api/index.json.jbuilder end # GET /api/v1/identifiers/:id def api_show - @identifiers = Identifier.where(project_id: sessions_current_project_id).find(params[:id]) - render '/identifiers/api/show.json.jbuilder' + @identifier = Identifier.where(project_id: sessions_current_project_id).find(params[:id]) + render '/identifiers/show.json.jbuilder'#######/identifiers/api/show.json.jbuilder end # GET /identifers/1 From 166b49b2533e970f3537aa90e839ebd55709b920 Mon Sep 17 00:00:00 2001 From: jrflood Date: Wed, 19 Aug 2020 11:18:56 -0500 Subject: [PATCH 007/189] move sources, people inside user_authenticated --- config/routes/api_v1.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/config/routes/api_v1.rb b/config/routes/api_v1.rb index b1e47a7e26..588da02bb8 100644 --- a/config/routes/api_v1.rb +++ b/config/routes/api_v1.rb @@ -8,17 +8,17 @@ get :ping, controller: 'ping' get :pingz, controller: 'ping' - get '/sources', to: '/sources#api_index' - get '/sources/:id', to: '/sources#api_show' - get '/sources/autocomplete', to: '/sources#autocomplete' - - get '/people', to: '/people#api_index' - get '/people/:id', to: '/people#api_show' - get '/people/autocomplete', to: '/people#autocomplete' - # authenticated by user_token defaults authenticate_user: true do get '/user_authenticated', to: 'base#index' + + get '/sources', to: '/sources#api_index' + get '/sources/:id', to: '/sources#api_show' + get '/sources/autocomplete', to: '/sources#autocomplete' + + get '/people', to: '/people#api_index' + get '/people/:id', to: '/people#api_show' + get '/people/autocomplete', to: '/people#autocomplete' end # authenticated by project token From 0ff7da7e0f25deeb5977804a01cd6fd6e61d087b Mon Sep 17 00:00:00 2001 From: jrflood Date: Thu, 20 Aug 2020 11:09:58 -0500 Subject: [PATCH 008/189] disable identifiers API endpoint --- app/controllers/identifiers_controller.rb | 16 ++++++++-------- config/routes/api_v1.rb | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/controllers/identifiers_controller.rb b/app/controllers/identifiers_controller.rb index c4c1a02225..8fae0c3ee0 100644 --- a/app/controllers/identifiers_controller.rb +++ b/app/controllers/identifiers_controller.rb @@ -19,16 +19,16 @@ def index end # GET /api/v1/identifiers - def api_index - @identifiers = Queries::Identifier::Filter.new(identifier_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) - render '/identifiers/index.json.jbuilder'#######/identifiers/api/index.json.jbuilder - end + # def api_index + # @identifiers = Queries::Identifier::Filter.new(identifier_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + # render '/identifiers/index.json.jbuilder'#######/identifiers/api/index.json.jbuilder + # end # GET /api/v1/identifiers/:id - def api_show - @identifier = Identifier.where(project_id: sessions_current_project_id).find(params[:id]) - render '/identifiers/show.json.jbuilder'#######/identifiers/api/show.json.jbuilder - end + # def api_show + # @identifier = Identifier.where(project_id: sessions_current_project_id).find(params[:id]) + # render '/identifiers/show.json.jbuilder'#######/identifiers/api/show.json.jbuilder + # end # GET /identifers/1 def show diff --git a/config/routes/api_v1.rb b/config/routes/api_v1.rb index 588da02bb8..3fe5801310 100644 --- a/config/routes/api_v1.rb +++ b/config/routes/api_v1.rb @@ -43,9 +43,9 @@ get '/taxon_names/autocomplete', to: '/taxon_names#autocomplete' get '/taxon_names/:id', to: '/taxon_names#api_show' - get '/identifiers', to: '/identifiers#api_index' - get '/identifiers/:id', to: '/identifiers#api_show' - get '/identifiers/autocomplete', to: '/identifiers#autocomplete' + # get '/identifiers', to: '/identifiers#api_index' + # get '/identifiers/:id', to: '/identifiers#api_show' + # get '/identifiers/autocomplete', to: '/identifiers#autocomplete' end From 2c44270be4a5cda57ad621df736ad1666362a2c5 Mon Sep 17 00:00:00 2001 From: jrflood Date: Thu, 20 Aug 2020 11:38:04 -0500 Subject: [PATCH 009/189] replicate jbuilders for people api endpoint --- app/controllers/people_controller.rb | 4 ++-- app/views/people/api/_attributes.json.jbuilder | 7 +++++++ app/views/people/api/_base_attributes.json.jbuilder | 8 ++++++++ app/views/people/api/index.json.jbuilder | 3 +++ app/views/people/api/show.json.jbuilder | 2 ++ 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 app/views/people/api/_attributes.json.jbuilder create mode 100644 app/views/people/api/_base_attributes.json.jbuilder create mode 100644 app/views/people/api/index.json.jbuilder create mode 100644 app/views/people/api/show.json.jbuilder diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index d318d6e399..861eaf07f5 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -22,13 +22,13 @@ def index # GET /api/v1/people def api_index @people = Queries::Person::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) - render '/people/index.json.jbuilder'######/people/api/index.json.jbuilder' + render '/people/api/index.json.jbuilder' end # GET /api/v1/people/:id def api_show @person = Person.find(params[:id]) - render '/people/show.json.jbuilder'########/people/api/show.json.jbuilder' + render '/people/api/show.json.jbuilder' end # GET /people/1 diff --git a/app/views/people/api/_attributes.json.jbuilder b/app/views/people/api/_attributes.json.jbuilder new file mode 100644 index 0000000000..9e97eaa486 --- /dev/null +++ b/app/views/people/api/_attributes.json.jbuilder @@ -0,0 +1,7 @@ +json.partial! '/people/base_attributes', person: person + +json.roles do + json.array!(person.roles) do |role| + json.partial! '/roles/attributes', role: role + end +end diff --git a/app/views/people/api/_base_attributes.json.jbuilder b/app/views/people/api/_base_attributes.json.jbuilder new file mode 100644 index 0000000000..bb72e207d7 --- /dev/null +++ b/app/views/people/api/_base_attributes.json.jbuilder @@ -0,0 +1,8 @@ +json.extract! person, :id, :type, :last_name, :first_name, :suffix, :prefix, + :cached, :year_born, :year_died, :year_active_start, :year_active_end, + :created_by_id, :updated_by_id, :created_at, :updated_at + +json.label_html person_autocomplete_tag(person) + +json.partial! '/shared/data/all/metadata', object: person + diff --git a/app/views/people/api/index.json.jbuilder b/app/views/people/api/index.json.jbuilder new file mode 100644 index 0000000000..8ffcd5992d --- /dev/null +++ b/app/views/people/api/index.json.jbuilder @@ -0,0 +1,3 @@ +json.array!(@people) do |person| + json.partial! '/people/attributes', person: person +end diff --git a/app/views/people/api/show.json.jbuilder b/app/views/people/api/show.json.jbuilder new file mode 100644 index 0000000000..5504ff572a --- /dev/null +++ b/app/views/people/api/show.json.jbuilder @@ -0,0 +1,2 @@ +json.partial! '/people/base_attributes', person: @person + From 3dcff096e1662651a733f668cffdb8c7459d83bb Mon Sep 17 00:00:00 2001 From: jrflood Date: Thu, 20 Aug 2020 11:54:53 -0500 Subject: [PATCH 010/189] replicate jbuilders for sources api endpoint --- app/controllers/sources_controller.rb | 2 +- .../sources/api/_attributes.json.jbuilder | 37 +++++++++++++++++++ .../sources/api/autocomplete.json.jbuilder | 13 +++++++ app/views/sources/api/index.json.jbuilder | 3 ++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 app/views/sources/api/_attributes.json.jbuilder create mode 100644 app/views/sources/api/autocomplete.json.jbuilder create mode 100644 app/views/sources/api/index.json.jbuilder diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb index c46fc2e9db..8e19177757 100644 --- a/app/controllers/sources_controller.rb +++ b/app/controllers/sources_controller.rb @@ -25,7 +25,7 @@ def index # GET /api/v1/sources def api_index @sources = Queries::Source::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) - render '/sources/index.json.jbuilder'#####/sources/api/index.json.jbuilder + render '/sources/api/index.json.jbuilder' end # GET /api/v1/sources/:id diff --git a/app/views/sources/api/_attributes.json.jbuilder b/app/views/sources/api/_attributes.json.jbuilder new file mode 100644 index 0000000000..8947615d83 --- /dev/null +++ b/app/views/sources/api/_attributes.json.jbuilder @@ -0,0 +1,37 @@ +json.extract! source, :id, :serial_id, :address, :annote, :author, +:booktitle, :chapter, :crossref, :edition, :editor, +:howpublished, :institution, :journal, :key, :month, :note, +:number, :organization, :pages, :publisher, :school, :series, +:title, :type, :volume, :doi, :abstract, :copyright, :language, +:stated_year, :verbatim, :cached, :cached_author_string, +:bibtex_type, :created_by_id, :updated_by_id, :cached_nomenclature_date, +:day, :year, :isbn, :issn, :verbatim_contents, :verbatim_keywords, +:language_id, :translator, :year_suffix, :url, :created_at, :updated_at + +json.partial! '/shared/data/all/metadata', object: source, klass: 'Source' + +json.source_in_project source_in_project?(source) +json.project_source_id project_source_for_source(source)&.id + +if source.type == 'Source::Bibtex' + + #TODO move to shared + json.author_roles(source.author_roles) do |role| + json.extract! role, :id, :position, :type + json.person do + json.partial! '/people/api/base_attributes', person: role.person + end + end + + #TODO move to shared + json.editor_roles(source.editor_roles) do |role| + json.extract! role, :id, :position, :type + json.person do + json.partial! '/people/api/base_attributes', person: role.person + end + end +end + +json.documents do |d| + d.array! source.documents, partial: '/documents/attributes', as: :document +end diff --git a/app/views/sources/api/autocomplete.json.jbuilder b/app/views/sources/api/autocomplete.json.jbuilder new file mode 100644 index 0000000000..8c92343871 --- /dev/null +++ b/app/views/sources/api/autocomplete.json.jbuilder @@ -0,0 +1,13 @@ +json.array! @sources do |s| + v = source_tag(s) + json.id s.id + json.label v + json.label_html v + json.is_in_project s.is_in_project?(sessions_current_project_id) + + json.response_values do + if params[:method] + json.set! params[:method], s.id + end + end +end diff --git a/app/views/sources/api/index.json.jbuilder b/app/views/sources/api/index.json.jbuilder new file mode 100644 index 0000000000..1223402547 --- /dev/null +++ b/app/views/sources/api/index.json.jbuilder @@ -0,0 +1,3 @@ +json.array!(@sources) do |source| + json.partial! '/sources/api/attributes', source: source +end From ee9539b342ea577a2b973195de97cf0b06289759 Mon Sep 17 00:00:00 2001 From: jrflood Date: Thu, 20 Aug 2020 14:34:38 -0500 Subject: [PATCH 011/189] amend show jbuilder for taxon_names api endpoint --- app/views/taxon_names/api/show.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/taxon_names/api/show.json.jbuilder b/app/views/taxon_names/api/show.json.jbuilder index 573cdc4514..fb498e64be 100644 --- a/app/views/taxon_names/api/show.json.jbuilder +++ b/app/views/taxon_names/api/show.json.jbuilder @@ -1 +1 @@ -json.partial! '/taxon_names/attributes', taxon_name: @taxon_name +json.partial! '/taxon_names/api/attributes', taxon_name: @taxon_name From 891fb5151c700d36416638d22cb177f3e9eade86 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 31 Jul 2020 16:49:56 -0500 Subject: [PATCH 012/189] interactive key --- .../concerns/shared/alternate_values.rb | 3 +- app/models/observation_matrix_row.rb | 9 ++ lib/interactive_key.rb | 100 ++++++++++++++++-- 3 files changed, 104 insertions(+), 8 deletions(-) diff --git a/app/models/concerns/shared/alternate_values.rb b/app/models/concerns/shared/alternate_values.rb index 60e0a98810..24b621505e 100644 --- a/app/models/concerns/shared/alternate_values.rb +++ b/app/models/concerns/shared/alternate_values.rb @@ -38,8 +38,7 @@ module ClassMethods # @param [:symbol] the column name/attribute # @param [String, Integer, etc] the value to look for # Use - # Source.with_alternate_value_on(:title, 'f - # oo') + # Source.with_alternate_value_on(:title, 'foo') def with_alternate_value_on(a, b) joins(:alternate_values).where(alternate_values: {alternate_value_object_attribute: a, value: b}) end diff --git a/app/models/observation_matrix_row.rb b/app/models/observation_matrix_row.rb index 988787ce72..85630e9a87 100644 --- a/app/models/observation_matrix_row.rb +++ b/app/models/observation_matrix_row.rb @@ -73,6 +73,15 @@ def current_taxon_name end end + def current_otu + case row_object_class_name + when 'Otu' + row_object + when 'CollectionObject' + row_object.current_otu + end + end + # TODO: belong in helpers def next_row observation_matrix.observation_matrix_rows.where("position > ?", position).order(:position).first diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index 1674ce603e..87fd23ccbb 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -19,6 +19,21 @@ class InteractiveKey #optional attribute to provide a list of rowIDs to limit the set "1|5|10" attr_accessor :row_filter + #optional attribute to sort the list of descriptors. Options: 'ordered', 'weighted', 'optimized', a default + attr_accessor :sorting + + #optional attribute to eliminate taxa with not scored descriptors + attr_accessor :eliminate_unknown + + #optional attribute number of allowed erros during identification + attr_accessor :error_tolerance + + #limit identification to a particular nomenclatural rank 'genus', 'species', 'otu' + attr_accessor :identified_to_rank + + #optional attribute: descriptors and states selected during identification + attr_accessor :selected_descriptors + #returns the list of Languages used as translations for descriptors @@ -39,7 +54,22 @@ class InteractiveKey #list of rows to be included into the matrix attr_accessor :rows_with_filter - def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, keyword_ids: nil, row_filter: nil) + #return the list of descriptors with selections + attr_accessor :used_descriptors + + #return the list of useful descriptors + attr_accessor :useful_descriptors + + #return the list of descriptors not useful for identification + attr_accessor :not_useful_descriptors + + #list of remaining rows + attr_accessor :remaining + + #list of eliminated rows + attr_accessor :eliminated + + def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, keyword_ids: nil, row_filter: nil, sorting: 'optimized', error_tolerance: 0, identified_to_rank: nil, eliminate_unknown: nil, selected_descriptors: nil) raise if observation_matrix_id.blank? || project_id.blank? @observation_matrix_id = observation_matrix_id @project_id = project_id @@ -52,6 +82,16 @@ def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, ke @descriptors_with_filter = descriptors_with_keywords @row_filter = row_filter @rows_with_filter = rows_with_filter + @sorting = sorting + @error_tolerance = error_tolerance + @eliminate_unknown = eliminate_unknown + @identified_to_rank = identified_to_rank + @selected_descriptors = selected_descriptors + @used_descriptors ### + @useful_descriptors #### + @not_useful_descriptors #### + @remaining ### + @eliminated ### end def observation_matrix @@ -59,7 +99,11 @@ def observation_matrix end def descriptors - observation_matrix.descriptors.where('NOT descriptors.weight = 0 OR descriptors.weight IS NULL').order(:position) + if @sorting = 'weighted' + observation_matrix.descriptors.where('NOT descriptors.weight = 0 OR descriptors.weight IS NULL').order('descriptors.weight DESC, descriptors.position') + else + observation_matrix.descriptors.where('NOT descriptors.weight = 0 OR descriptors.weight IS NULL').order(:position) + end end def descriptor_available_languages @@ -96,7 +140,8 @@ def descriptors_with_keywords end def rows - ObservationMatrixRow.where(observation_matrix_id: @observation_matrix_id) + observation_matrix.reorder_rows(by = 'nomenclature') +# ObservationMatrixRow.where(observation_matrix_id: @observation_matrix_id) end def rows_with_filter @@ -105,13 +150,44 @@ def rows_with_filter else rows.where('observation_matrix_rows.id IN (?)', @row_filter.to_s.split('|')) end + end + def row_hash + h = {} + rows_with_filter.each do |r| + h[r.id] = {} + h[r.id][:object] = r + if @identified_to_rank == 'otu' + h[r.id][:object_at_rank] = r.current_otu || r + elsif @identified_to_rank + h[r.id][:object_at_rank] = r.current_taxon_name.ancestor_at_rank(@identified_to_rank, inlude_self = true) || r + else + h[r.id][:object_at_rank] = r + end + h[r.id][:errors] = 0 + end + h end - def descriptor_import_predicate - ###TODO import_attribute 'char_weight' exclude characters with weight == 0 + def descriptors_hash + h = {} + descriptors_with_keywords.each do |d| + h[d.id] = {} + h[d.id][:descriptor] = d + h[d.id][:states] = {} + h[d.id][:observations] = {} + end + @observation_matrix.observations.each do |o| + if h[o.descriptor_id] + h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s] = [] if h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s].nil? + h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s] += [o] + h[o.descriptor_id][:states][o.character_state_id] = {} if o.character_state_id + end + end + h end + def observations # id # descriptor_id @@ -133,7 +209,19 @@ def observations ### types: Qualitative(char_states); Presence absence; Quantitative (single measurement); Sample (min, max); Free text end - # rst = All characters ordered by Characters.Weight DESC, Characters.Char, State.State" + +=begin + not numeric + weight = rem_taxa/number_of_states + squer (sum (rem_taxa/number_of_states - taxa_in_each_state)^2) + + numeric for each measurement for a particular species + i = max - min ; if 0 then (numMax - numMin) / 10 + sum of all i + if numMax = numMin then numMax = numMax + 0.00001 + weight = rem_taxa * (sum of i / number of measuments for taxon / (numMax - numMin) ) * (2 - number of measuments for taxon / rem_taxa) +=end + + # rst = All characters ordered by Characters.Weight DESC, Characters.Char, State.State" # rst2 = List of all taxa from the key ordered by hiercode # filter = taxa with specic IDs # list of used states From 81653b404b2aa95fdf93faf24f847df2ed81040e Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Wed, 5 Aug 2020 15:22:35 -0500 Subject: [PATCH 013/189] interactive key --- lib/interactive_key.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index 87fd23ccbb..eb035aa9e5 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -152,6 +152,10 @@ def rows_with_filter end end + ## row_hash: {row.id: {:object, ### (collection_object or OTU) + ## :object_at_rank, ### (converted to OTU or TN) + ## :errors, ### (calculated number of errors) + ## :status }} ### ('remaining', 'eliminated') def row_hash h = {} rows_with_filter.each do |r| @@ -165,10 +169,15 @@ def row_hash h[r.id][:object_at_rank] = r end h[r.id][:errors] = 0 + h[r.id][:status] = 'remaining' end h end + ## descriptors_hash: {descriptor.id: {:descriptor, ### (descriptor) + ## :states, ### (hash of states) + ## :errors, ### (calculated number of errors) + ## :status }} ### ('remaining', 'eliminated') def descriptors_hash h = {} descriptors_with_keywords.each do |d| From 6355f2335ed71eb05b622ae7192a22f70d46eab4 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Thu, 6 Aug 2020 13:48:50 -0500 Subject: [PATCH 014/189] interactive key --- lib/interactive_key.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index eb035aa9e5..6e3d257073 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -175,27 +175,33 @@ def row_hash end ## descriptors_hash: {descriptor.id: {:descriptor, ### (descriptor) - ## :states, ### (hash of states) - ## :errors, ### (calculated number of errors) - ## :status }} ### ('remaining', 'eliminated') + ## :observations, ### (array of observations for ) + ## :state_ids, ### {hash of state_ids used in the particular matrix} + ## }} def descriptors_hash h = {} descriptors_with_keywords.each do |d| h[d.id] = {} h[d.id][:descriptor] = d - h[d.id][:states] = {} + h[d.id][:states_ids] = {} h[d.id][:observations] = {} end @observation_matrix.observations.each do |o| if h[o.descriptor_id] h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s] = [] if h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s].nil? h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s] += [o] - h[o.descriptor_id][:states][o.character_state_id] = {} if o.character_state_id + h[o.descriptor_id][:state_ids][o.character_state_id] = {} if o.character_state_id end end h end + def remaining_taxa + row_hash.each do |r| + + end + end + def observations # id From c5224fc6c55c658a2b3d142bde281b8da55daa00 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Thu, 6 Aug 2020 16:38:46 -0500 Subject: [PATCH 015/189] interactive key --- lib/interactive_key.rb | 87 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 15 deletions(-) diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index 6e3d257073..4e50ba7cf4 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -22,7 +22,7 @@ class InteractiveKey #optional attribute to sort the list of descriptors. Options: 'ordered', 'weighted', 'optimized', a default attr_accessor :sorting - #optional attribute to eliminate taxa with not scored descriptors + #optional attribute to eliminate taxa with not scored descriptors: 'false' - default or 'true' attr_accessor :eliminate_unknown #optional attribute number of allowed erros during identification @@ -31,7 +31,7 @@ class InteractiveKey #limit identification to a particular nomenclatural rank 'genus', 'species', 'otu' attr_accessor :identified_to_rank - #optional attribute: descriptors and states selected during identification + #optional attribute: descriptors and states selected during identification "123:1|3||125:3|5||135:2" attr_accessor :selected_descriptors @@ -69,6 +69,16 @@ class InteractiveKey #list of eliminated rows attr_accessor :eliminated + #hash of used descriptors and their states + attr_accessor :selected_descriptors_hash + + #temporary hash of rows; used for calculation of remaining and eliminated rows + attr_accessor :row_hash + + #temporary hash of descriptors; used for calculation of useful and not useful characters and their states + attr_accessor :descriptors_hash + + def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, keyword_ids: nil, row_filter: nil, sorting: 'optimized', error_tolerance: 0, identified_to_rank: nil, eliminate_unknown: nil, selected_descriptors: nil) raise if observation_matrix_id.blank? || project_id.blank? @observation_matrix_id = observation_matrix_id @@ -83,15 +93,23 @@ def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, ke @row_filter = row_filter @rows_with_filter = rows_with_filter @sorting = sorting - @error_tolerance = error_tolerance - @eliminate_unknown = eliminate_unknown + @error_tolerance = error_tolerance.to_i + @eliminate_unknown = eliminate_unknown == 'true' ? true : false @identified_to_rank = identified_to_rank @selected_descriptors = selected_descriptors + @selected_descriptors_hash = selected_descriptors_hash_initiate + @row_hash = row_hash_initiate + @descriptors_hash = descriptors_hash_initiate + + #main_logic + @remaining = remaining_taxa + @eliminated ### @used_descriptors ### @useful_descriptors #### @not_useful_descriptors #### - @remaining ### - @eliminated ### + + @row_hash = nil + @descriptors_hash = nil end def observation_matrix @@ -156,7 +174,7 @@ def rows_with_filter ## :object_at_rank, ### (converted to OTU or TN) ## :errors, ### (calculated number of errors) ## :status }} ### ('remaining', 'eliminated') - def row_hash + def row_hash_initiate h = {} rows_with_filter.each do |r| h[r.id] = {} @@ -178,27 +196,66 @@ def row_hash ## :observations, ### (array of observations for ) ## :state_ids, ### {hash of state_ids used in the particular matrix} ## }} - def descriptors_hash + def descriptors_hash_initiate h = {} descriptors_with_keywords.each do |d| h[d.id] = {} h[d.id][:descriptor] = d - h[d.id][:states_ids] = {} - h[d.id][:observations] = {} + h[d.id][:states_ids] = [] if d.type == 'Descriptor::Qualitative' # array of used state_ids + h[d.id][:min] = 999999 if d.type == 'Descriptor::Continuous' || d.type == 'Descriptor::Sample' # min value used as continuous or sample + h[d.id][:max] = -999999 if d.type == 'Descriptor::Continuous' || d.type == 'Descriptor::Sample' # max value used as continuous or sample + h[d.id][:observations] = [] end - @observation_matrix.observations.each do |o| + t = "'Observation::Continuous', 'Observation::PresenceAbsence', 'Observation::Qualitative', 'Observation::Sample'" + @observation_matrix.observations.where('"observations"."type" IN (' + t + ')').each do |o| if h[o.descriptor_id] - h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s] = [] if h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s].nil? - h[o.descriptor_id][:observations][o.otu_id.to_s + '|' + o.collection_object_id.to_s] += [o] - h[o.descriptor_id][:state_ids][o.character_state_id] = {} if o.character_state_id + otu_collection_object = o.otu_id.to_s + '|' + o.collection_object_id.to_s + h[o.descriptor_id][:observations][otu_collection_object] = [] if h[o.descriptor_id][:observations][otu_collection_object].nil? + h[o.descriptor_id][:observations][otu_collection_object] += [o] + h[o.descriptor_id][:state_ids] += [o.character_state_id.to_s] if o.character_state_id + h[o.descriptor_id][:min] = o.continuous_value if o.continuous_value && o.character_state_id < h[o.descriptor_id][:min] + h[o.descriptor_id][:max] = o.continuous_value if o.continuous_value && o.character_state_id > h[o.descriptor_id][:max] + h[o.descriptor_id][:min] = o.sample_min if o.sample_min && o.sample_min < h[o.descriptor_id][:min] + h[o.descriptor_id][:max] = o.sample_max if o.sample_max && o.sample_max > h[o.descriptor_id][:max] end end h end + # returns {123: ['1', '3'], 125: ['3', '5'], 135: ['2']} + def selected_descriptors_hash_initiate + # "123:1|3||125:3|5||135:2" + h = {} + a = @selected_descriptors.split('||') + a.each do |i| + d = i.split(':') + h[d[0]].to_i = d[1].split('|') + end + h + end + def remaining_taxa - row_hash.each do |r| +# @error_tolerance = error_tolerance +# @eliminate_unknown = eliminate_unknown + + @row_hash.each do |r_key, r_value| + @selected_descriptors_hash.each do |d_key, d_value| + otu_collection_object = r_value[:object].otu_id.to_s + '|' + r_value[:object].collection_object_id.to_s + if @eliminate_unknown && @descriptors_hash[d_key][:observations][otu_collection_object].nil? + r_value[:errors] += 1 + elsif @descriptors_hash[d_key][:observations][otu_collection_object].nil? + #character not scored but no error + else + case @descriptors_hash[d_key][:descriptor].type + when 'Descriptor::Continuous' + when 'Descriptor::PresenceAbsence' + when 'Descriptor::Qualitative' + when 'Descriptor::Sample' + end + + end + end end end From 872cf370d77022c5cc22ff68c7e8a494dc594043 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Wed, 26 Aug 2020 16:57:01 -0500 Subject: [PATCH 016/189] interactive key --- lib/interactive_key.rb | 71 +++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index 4e50ba7cf4..bc919e8390 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -103,7 +103,7 @@ def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, ke #main_logic @remaining = remaining_taxa - @eliminated ### + @eliminated = eliminated_taxa @used_descriptors ### @useful_descriptors #### @not_useful_descriptors #### @@ -187,7 +187,8 @@ def row_hash_initiate h[r.id][:object_at_rank] = r end h[r.id][:errors] = 0 - h[r.id][:status] = 'remaining' + h[r.id][:error_descriptors] = {} + h[r.id][:status] = 'remaining' ### if number of errors > @error_tolerance, replaced to 'eliminated' end h end @@ -204,25 +205,30 @@ def descriptors_hash_initiate h[d.id][:states_ids] = [] if d.type == 'Descriptor::Qualitative' # array of used state_ids h[d.id][:min] = 999999 if d.type == 'Descriptor::Continuous' || d.type == 'Descriptor::Sample' # min value used as continuous or sample h[d.id][:max] = -999999 if d.type == 'Descriptor::Continuous' || d.type == 'Descriptor::Sample' # max value used as continuous or sample - h[d.id][:observations] = [] + h[d.id][:observations] = [] # all observation for a particular + h[d.id][:observation_hash] = [] ### state_ids, true/false for a particular descriptor/otu_id/catalog_id combination (for PresenceAbsence or Qualitative or Continuous) end t = "'Observation::Continuous', 'Observation::PresenceAbsence', 'Observation::Qualitative', 'Observation::Sample'" @observation_matrix.observations.where('"observations"."type" IN (' + t + ')').each do |o| if h[o.descriptor_id] otu_collection_object = o.otu_id.to_s + '|' + o.collection_object_id.to_s - h[o.descriptor_id][:observations][otu_collection_object] = [] if h[o.descriptor_id][:observations][otu_collection_object].nil? - h[o.descriptor_id][:observations][otu_collection_object] += [o] + h[o.descriptor_id][:observations][otu_collection_object] = [] if h[o.descriptor_id][:observations][otu_collection_object].nil? #?????? + h[o.descriptor_id][:observations][otu_collection_object] += [o] #?????? h[o.descriptor_id][:state_ids] += [o.character_state_id.to_s] if o.character_state_id h[o.descriptor_id][:min] = o.continuous_value if o.continuous_value && o.character_state_id < h[o.descriptor_id][:min] h[o.descriptor_id][:max] = o.continuous_value if o.continuous_value && o.character_state_id > h[o.descriptor_id][:max] h[o.descriptor_id][:min] = o.sample_min if o.sample_min && o.sample_min < h[o.descriptor_id][:min] h[o.descriptor_id][:max] = o.sample_max if o.sample_max && o.sample_max > h[o.descriptor_id][:max] + h[o.descriptor_id][:observation_hash][otu_collection_object] = [] if h[o.descriptor_id][:observation_hash][otu_collection_object].nil? + h[o.descriptor_id][:observation_hash][otu_collection_object] += [o.character_state_id.to_s] if o.character_state_id + h[o.descriptor_id][:observation_hash][otu_collection_object] += [o.continuous_value.to_s] if o.continuous_value + h[o.descriptor_id][:observation_hash][otu_collection_object] += [o.presence.to_s] unless o.presence.nil? end end h end - # returns {123: ['1', '3'], 125: ['3', '5'], 135: ['2']} + # returns {123: ['1', '3'], 125: ['3', '5'], 135: ['2'], 136: ['true'], 140: ['5-10']} def selected_descriptors_hash_initiate # "123:1|3||125:3|5||135:2" h = {} @@ -235,30 +241,67 @@ def selected_descriptors_hash_initiate end def remaining_taxa -# @error_tolerance = error_tolerance -# @eliminate_unknown = eliminate_unknown +# @error_tolerance - integer +# @eliminate_unknown 'true' or 'false' +# @descriptors_hash + h = {} @row_hash.each do |r_key, r_value| @selected_descriptors_hash.each do |d_key, d_value| otu_collection_object = r_value[:object].otu_id.to_s + '|' + r_value[:object].collection_object_id.to_s - if @eliminate_unknown && @descriptors_hash[d_key][:observations][otu_collection_object].nil? + if @eliminate_unknown && @descriptors_hash[d_key][:observation_hash][otu_collection_object].nil? r_value[:errors] += 1 - elsif @descriptors_hash[d_key][:observations][otu_collection_object].nil? + r_value[:error_descriptors][@descriptors_hash[d_key][:descriptor]] = [] + elsif @descriptors_hash[d_key][:observation_hash][otu_collection_object].nil? #character not scored but no error else case @descriptors_hash[d_key][:descriptor].type when 'Descriptor::Continuous' + r_value[:errors] += 1 if (@descriptors_hash[d_key][:observation_hash][otu_collection_object] & d_value).empty? + r_value[:error_descriptors][@descriptors_hash[d_key][:descriptor]] = @descriptors_hash[d_key][:observations][otu_collection_object] when 'Descriptor::PresenceAbsence' - when 'Descriptor::Qualitative' - when 'Descriptor::Sample' + r_value[:errors] += 1 if (@descriptors_hash[d_key][:observation_hash][otu_collection_object] & d_value).empty? + r_value[:error_descriptors][@descriptors_hash[d_key][:descriptor]] = @descriptors_hash[d_key][:observations][otu_collection_object] + when 'Descriptor::Qualitative' + r_value[:errors] += 1 if (@descriptors_hash[d_key][:observation_hash][otu_collection_object] & d_value).empty? + r_value[:error_descriptors][@descriptors_hash[d_key][:descriptor]] = @descriptors_hash[d_key][:observations][otu_collection_object] + when 'Descriptor::Sample' + p = false + a = d_value.split('-') + d_min = a[0] + d_max = a[1].nil? ? a[0] : a[1] + @descriptors_hash[d_key][:observations][otu_collection_object].each do |o| + p = true if o.sample_min <= d_min.to_i || o.sample_max >= d_max.to_i + end + r_value[:errors] += 1 if p = false + r_value[:error_descriptors][@descriptors_hash[d_key][:descriptor]] = @descriptors_hash[d_key][:observations][otu_collection_object] end - end - + end + if r_value[:errors] > @error_tolerance + r_value[:status] = 'eliminated' + else + h[r_value[:object_at_rank]] = true if h[r_value[:object_at_rank]].nil? end end + return h end + def eliminated_taxa + h = {} + @row_hash.each do |r_key, r_value| + if r_value[:status] == 'eliminated' && @ramaining[r_value[:object_at_rank]].nil? + if h[r_value[:object_at_rank]].nil? + h[r_value[:object_at_rank]] = {} + h[r_value[:object_at_rank]][:error_descriptors] = {} + end + r_value[:error_descriptors].each do |e, o| + h[r_value[:object_at_rank]][:error_descriptors][e] = o if h[r_value[:object_at_rank]][:error_descriptors][e].nil? + end + end + end + return h + end def observations # id From a9eca5b549c61385c8c41774581b381d6e1ab0c6 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Tue, 8 Sep 2020 17:41:07 -0500 Subject: [PATCH 017/189] interactive key --- lib/interactive_key.rb | 80 +++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index bc919e8390..4f1e03e888 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -104,8 +104,8 @@ def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, ke #main_logic @remaining = remaining_taxa @eliminated = eliminated_taxa + @useful_descriptors = useful_descriptors @used_descriptors ### - @useful_descriptors #### @not_useful_descriptors #### @row_hash = nil @@ -170,25 +170,26 @@ def rows_with_filter end end - ## row_hash: {row.id: {:object, ### (collection_object or OTU) + ## row_hash: {otu_collection_object: {:object, ### (collection_object or OTU) ## :object_at_rank, ### (converted to OTU or TN) ## :errors, ### (calculated number of errors) ## :status }} ### ('remaining', 'eliminated') def row_hash_initiate h = {} rows_with_filter.each do |r| - h[r.id] = {} - h[r.id][:object] = r + otu_collection_object = r.otu_id.to_s + '|' + r.collection_object_id.to_s + h[otu_collection_object] = {} + h[otu_collection_object][:object] = r if @identified_to_rank == 'otu' - h[r.id][:object_at_rank] = r.current_otu || r + h[otu_collection_object][:object_at_rank] = r.current_otu || r elsif @identified_to_rank - h[r.id][:object_at_rank] = r.current_taxon_name.ancestor_at_rank(@identified_to_rank, inlude_self = true) || r + h[otu_collection_object][:object_at_rank] = r.current_taxon_name.ancestor_at_rank(@identified_to_rank, inlude_self = true) || r else - h[r.id][:object_at_rank] = r + h[otu_collection_object][:object_at_rank] = r end - h[r.id][:errors] = 0 - h[r.id][:error_descriptors] = {} - h[r.id][:status] = 'remaining' ### if number of errors > @error_tolerance, replaced to 'eliminated' + h[otu_collection_object][:errors] = 0 + h[otu_collection_object][:error_descriptors] = {} + h[otu_collection_object][:status] = 'remaining' ### if number of errors > @error_tolerance, replaced to 'eliminated' end h end @@ -202,11 +203,13 @@ def descriptors_hash_initiate descriptors_with_keywords.each do |d| h[d.id] = {} h[d.id][:descriptor] = d - h[d.id][:states_ids] = [] if d.type == 'Descriptor::Qualitative' # array of used state_ids + h[d.id][:weight_index] = 0 + h[d.id][:state_ids] = {} if d.type == 'Descriptor::Qualitative' # hash of used state_ids h[d.id][:min] = 999999 if d.type == 'Descriptor::Continuous' || d.type == 'Descriptor::Sample' # min value used as continuous or sample h[d.id][:max] = -999999 if d.type == 'Descriptor::Continuous' || d.type == 'Descriptor::Sample' # max value used as continuous or sample h[d.id][:observations] = [] # all observation for a particular h[d.id][:observation_hash] = [] ### state_ids, true/false for a particular descriptor/otu_id/catalog_id combination (for PresenceAbsence or Qualitative or Continuous) + h[d.id][:status] = 'useful' ### 'used', 'useful', 'useless' end t = "'Observation::Continuous', 'Observation::PresenceAbsence', 'Observation::Qualitative', 'Observation::Sample'" @observation_matrix.observations.where('"observations"."type" IN (' + t + ')').each do |o| @@ -214,7 +217,6 @@ def descriptors_hash_initiate otu_collection_object = o.otu_id.to_s + '|' + o.collection_object_id.to_s h[o.descriptor_id][:observations][otu_collection_object] = [] if h[o.descriptor_id][:observations][otu_collection_object].nil? #?????? h[o.descriptor_id][:observations][otu_collection_object] += [o] #?????? - h[o.descriptor_id][:state_ids] += [o.character_state_id.to_s] if o.character_state_id h[o.descriptor_id][:min] = o.continuous_value if o.continuous_value && o.character_state_id < h[o.descriptor_id][:min] h[o.descriptor_id][:max] = o.continuous_value if o.continuous_value && o.character_state_id > h[o.descriptor_id][:max] h[o.descriptor_id][:min] = o.sample_min if o.sample_min && o.sample_min < h[o.descriptor_id][:min] @@ -236,6 +238,7 @@ def selected_descriptors_hash_initiate a.each do |i| d = i.split(':') h[d[0]].to_i = d[1].split('|') + @descriptors_hash[h[d[0]].to_i][:status] = 'used' end h end @@ -303,6 +306,59 @@ def eliminated_taxa return h end + def useful_descriptors + list_of_remaining_taxa = {} + @row_hash.each do |r_key, r_value| + if r_value[:status] != 'eliminated' && d_value[:status] != 'used' + list_of_remaining_taxa[r_value[:object_at_rank] ] = true + end + end + number_of_taxa = list_of_remaining_taxa.count + + @descriptors_hash.each do |d_key, d_value| + d_value[:observations].each do |otu_key, otu_value| + otu_collection_object = otu_key + if @row_hash[otu_collection_object][:status] != 'eliminated' + otu_value.each do |o| + if o.character_state_id + d_key[:state_ids][o.character_state_id.to_s] = {} if d_key[:state_ids][o.character_state_id.to_s].nil? + d_key[:state_ids][o.character_state_id.to_s][:rows] = {} if d_key[:state_ids][o.character_state_id.to_s][:rows].nil? ## rows which this state identifies + d_key[:state_ids][o.character_state_id.to_s][:rows][ @row_hash[otu_collection_object][:object_at_rank] ] = true + d_key[:state_ids][o.character_state_id.to_s][:status] = 'useful' ## 'used', 'useful', 'useless' + end + unless o.presence.nil? + d_key[:state_ids][o.presence.to_s] = {} if d_key[:state_ids][o.presence.to_s].nil? + d_key[:state_ids][o.presence.to_s][:rows] = {} if d_key[:state_ids][o.presence.to_s][:rows].nil? ## rows which this state identifies + d_key[:state_ids][o.presence.to_s][:rows][ @row_hash[otu_collection_object][:object_at_rank] ] = true + d_key[:state_ids][o.presence.to_s][:status] = 'useful' ## 'used', 'useful', 'useless' + end + + end + end + + end + + + @row_hash.each do |r_key, r_value| + if r_value[:status] != 'eliminated' && d_value[:status] != 'used' + + + + # not numeric + # weight = rem_taxa/number_of_states + squer (sum (rem_taxa/number_of_states - taxa_in_each_state)^2) + + # numeric for each measurement for a particular species + # i = max - min ; if 0 then (numMax - numMin) / 10 + # sum of all i + # if numMax = numMin then numMax = numMax + 0.00001 + # weight = rem_taxa * (sum of i / number of measuments for taxon / (numMax - numMin) ) * (2 - number of measuments for taxon / rem_taxa) + + + end + end + end + end + def observations # id # descriptor_id From a8415bb7c2fa3143eb8d0067ecb5c2bc2f8cc13a Mon Sep 17 00:00:00 2001 From: jrflood Date: Wed, 9 Sep 2020 16:40:01 -0500 Subject: [PATCH 018/189] groundwork for collection_objects api endpoint --- .../collection_objects_controller.rb | 42 ++++++++++++------- app/controllers/sources_controller.rb | 2 +- .../api/_attributes.json.jbuilder | 13 ++++++ .../api/autocomplete.json.jbuilder | 13 ++++++ .../api/index.json.jbuilder | 1 + .../collection_objects/api/show.json.jbuilder | 5 +++ config/routes/api_v1.rb | 4 ++ 7 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 app/views/collection_objects/api/_attributes.json.jbuilder create mode 100644 app/views/collection_objects/api/autocomplete.json.jbuilder create mode 100644 app/views/collection_objects/api/index.json.jbuilder create mode 100644 app/views/collection_objects/api/show.json.jbuilder diff --git a/app/controllers/collection_objects_controller.rb b/app/controllers/collection_objects_controller.rb index 8ad281cf36..a9dbcd8294 100644 --- a/app/controllers/collection_objects_controller.rb +++ b/app/controllers/collection_objects_controller.rb @@ -23,9 +23,21 @@ def index end end + # GET /api/v1/collection_objects + def api_index + @collection_objects = Queries::CollectionObject::Filter.new(filter_params).all.page(params[:page]).per([ [(params[:per] || 100).to_i, 1000].min, 1].max) + render '/collection_objects/api/index.json.jbuilder' + end + + # GET /api/v1/collection_objects/:id + def api_show + @collection_objects = CollectionObject.find(params[:id]) + render '/collection_objects/show.json.jbuilder' + end + def biocuration_classifications @biocuration_classifications = @collection_object.biocuration_classifications - render '/biocuration_classifications/index' + render '/biocuration_classifications/index' end # DEPRECATED @@ -38,8 +50,8 @@ def dwca # Render DWC fields *only* def dwc_index objects = filtered_collection_objects.includes(:dwc_occurrence).all - assign_pagination(objects) - + assign_pagination(objects) + @objects = objects.pluck( ::CollectionObject.dwc_attribute_vector ) @klass = ::CollectionObject render '/dwc_occurrences/dwc_index' @@ -52,9 +64,9 @@ def dwc o = CollectionObject.find(params[:id]) if params[:rebuild] == 'true' # get does not rebuild - o.set_dwc_occurrence + o.set_dwc_occurrence else - o.get_dwc_occurrence + o.get_dwc_occurrence end end render json: o.dwc_occurrence_attribute_values @@ -68,16 +80,16 @@ def dwc_verbose if params[:rebuild] == 'true' # get does not rebuild - o.set_dwc_occurrence + o.set_dwc_occurrence else - o.get_dwc_occurrence + o.get_dwc_occurrence end end render json: o.dwc_occurrence_attributes end # Intent is DWC fields + quick summary fields for reports - # !! As currently implemented rebuilds DWC all + # !! As currently implemented rebuilds DWC all def report @collection_objects = filtered_collection_objects.includes(:dwc_occurrence) end @@ -190,10 +202,10 @@ def search def autocomplete @collection_objects = - Queries::CollectionObject::Autocomplete.new( - params[:term], - project_id: sessions_current_project_id - ).autocomplete + Queries::CollectionObject::Autocomplete.new( + params[:term], + project_id: sessions_current_project_id + ).autocomplete end # GET /collection_objects/download @@ -356,7 +368,7 @@ def filter_params a = params.permit( :recent, Queries::CollectingEvent::Filter::ATTRIBUTES, - :ancestor_id, + :ancestor_id, :collection_object_type, :current_determinations, :depicted, @@ -393,7 +405,7 @@ def filter_params geographic_area_ids: [], biocuration_class_ids: [], biological_relationship_ids: [] - + # collecting_event: { # :recent, # keyword_ids: [] @@ -402,7 +414,7 @@ def filter_params a[:user_id] = params[:user_id] if params[:user_id] && is_project_member_by_id(params[:user_id], sessions_current_project_id) # double check vs. setting project_id from API a - end + end end diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb index 8e19177757..44b3aecac5 100644 --- a/app/controllers/sources_controller.rb +++ b/app/controllers/sources_controller.rb @@ -31,7 +31,7 @@ def api_index # GET /api/v1/sources/:id def api_show @source = Source.find(params[:id]) - render '/sources/show.json.jbuilder'######/sources/api/show.json.jbuilder + render '/sources/show.json.jbuilder' end def list diff --git a/app/views/collection_objects/api/_attributes.json.jbuilder b/app/views/collection_objects/api/_attributes.json.jbuilder new file mode 100644 index 0000000000..1194496fc7 --- /dev/null +++ b/app/views/collection_objects/api/_attributes.json.jbuilder @@ -0,0 +1,13 @@ +json.extract! collection_object, :id, :total, :preparation_type_id, :collecting_event_id, :repository_id, :type, +:buffered_collecting_event, :buffered_determinations, :buffered_other_labels, +:ranged_lot_category_id, :accessioned_at, :deaccessioned_at, :deaccession_reason, +:created_by_id, :updated_by_id, :project_id, :created_at, :updated_at + +# Not sure if needed, virtual attribute setter +json.contained_in collection_object.contained_in + +if collection_object.contained? + json.container_id collection_object.container.id +end + +json.partial! '/shared/data/all/metadata', object: collection_object diff --git a/app/views/collection_objects/api/autocomplete.json.jbuilder b/app/views/collection_objects/api/autocomplete.json.jbuilder new file mode 100644 index 0000000000..8a6a55daac --- /dev/null +++ b/app/views/collection_objects/api/autocomplete.json.jbuilder @@ -0,0 +1,13 @@ +json.array! @collection_objects do |s| + v = collection_object_autocomplete_tag(s) + json.id s.id + json.label label_for_collection_object(s) + json.gid s.to_global_id.to_s + json.label_html v + + json.response_values do + if params[:method] + json.set! params[:method], s.id + end + end +end diff --git a/app/views/collection_objects/api/index.json.jbuilder b/app/views/collection_objects/api/index.json.jbuilder new file mode 100644 index 0000000000..b75b820077 --- /dev/null +++ b/app/views/collection_objects/api/index.json.jbuilder @@ -0,0 +1 @@ +json.partial! '/collection_objects/api/attributes', collection: @collection_objects, as: :collection_object diff --git a/app/views/collection_objects/api/show.json.jbuilder b/app/views/collection_objects/api/show.json.jbuilder new file mode 100644 index 0000000000..0e09b18bd2 --- /dev/null +++ b/app/views/collection_objects/api/show.json.jbuilder @@ -0,0 +1,5 @@ +json.partial! '/collection_objects/api/attributes', collection_object: @collection_object + +# curl 'http://localhost:3000/api/v1/collection_objects/3?token=FindYourOwnToken&project_id=1&include=geo_json' +# wget "http://localhost:3000/api/v1/collection_objects/3?token=FindYourOwnToken&project_id=1&include=geo_json" -O tmp/test.json + diff --git a/config/routes/api_v1.rb b/config/routes/api_v1.rb index 3fe5801310..dfbdeb765a 100644 --- a/config/routes/api_v1.rb +++ b/config/routes/api_v1.rb @@ -43,6 +43,10 @@ get '/taxon_names/autocomplete', to: '/taxon_names#autocomplete' get '/taxon_names/:id', to: '/taxon_names#api_show' + get '/collection_objects', to: '/identifiers#api_index' + get '/collection_objects/:id', to: '/identifiers#api_show' + get '/collection_objects/autocomplete', to: '/identifiers#autocomplete' + # get '/identifiers', to: '/identifiers#api_index' # get '/identifiers/:id', to: '/identifiers#api_show' # get '/identifiers/autocomplete', to: '/identifiers#autocomplete' From cedccf5411f944024c66fff3aba9caca0ebdb59b Mon Sep 17 00:00:00 2001 From: jrflood Date: Wed, 9 Sep 2020 18:48:05 -0500 Subject: [PATCH 019/189] heartbeat for collection_objects api endpoint --- config/routes/api_v1.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/config/routes/api_v1.rb b/config/routes/api_v1.rb index dfbdeb765a..24b548d773 100644 --- a/config/routes/api_v1.rb +++ b/config/routes/api_v1.rb @@ -19,6 +19,11 @@ get '/people', to: '/people#api_index' get '/people/:id', to: '/people#api_show' get '/people/autocomplete', to: '/people#autocomplete' + + get '/collection_objects', to: '/collection_objects#api_index' + get '/collection_objects/:id', to: '/collection_objects#api_show' + get '/collection_objects/autocomplete', to: '/collection_objects#autocomplete' + end # authenticated by project token @@ -43,10 +48,6 @@ get '/taxon_names/autocomplete', to: '/taxon_names#autocomplete' get '/taxon_names/:id', to: '/taxon_names#api_show' - get '/collection_objects', to: '/identifiers#api_index' - get '/collection_objects/:id', to: '/identifiers#api_show' - get '/collection_objects/autocomplete', to: '/identifiers#autocomplete' - # get '/identifiers', to: '/identifiers#api_index' # get '/identifiers/:id', to: '/identifiers#api_show' # get '/identifiers/autocomplete', to: '/identifiers#autocomplete' From 97a40660736307a7834fb78094d76d0bca08a50a Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 11 Sep 2020 17:32:43 -0500 Subject: [PATCH 020/189] interactive key --- app/models/character_state.rb | 26 ++++++- app/models/descriptor.rb | 26 ++++++- lib/interactive_key.rb | 124 ++++++++++++++++++++++++++++------ 3 files changed, 152 insertions(+), 24 deletions(-) diff --git a/app/models/character_state.rb b/app/models/character_state.rb index ab8c388753..905e0b22ef 100644 --- a/app/models/character_state.rb +++ b/app/models/character_state.rb @@ -25,7 +25,7 @@ class CharacterState < ApplicationRecord acts_as_list scope: [:descriptor_id] - ALTERNATE_VALUES_FOR = [:name, :label].freeze + ALTERNATE_VALUES_FOR = [:name, :label, :description_name, :key_name].freeze belongs_to :descriptor, inverse_of: :character_states, class_name: 'Descriptor::Qualitative' has_many :observations, inverse_of: :character_state, dependent: :restrict_with_error @@ -44,4 +44,28 @@ def descriptor_kind errors.add(:descriptor, 'must be Descriptor::Qualitative') if descriptor && descriptor.type != 'Descriptor::Qualitative' end + ## retrunrs string, name of the character_state in a particular language + # target: :key, :description, nil + def target_name(target, language_id) + n = self.name + a = nil + case target + when :key + n = self.key_name.nil? ? n : self.key_name + when :description + n = self.description_name.nil? ? n : self.description_name + end + unless language_id.nil? + case target + when :key + a = AlternateValue::Translation.where(alternate_value_object: self, language_id: language_id, alternate_value_object_attribute: 'key_name').first + when :description + a = AlternateValue::Translation.where(alternate_value_object: self, language_id: language_id, alternate_value_object_attribute: 'description_name').first + end + a = AlternateValue::Translation.where(alternate_value_object: self, language_id: language_id, alternate_value_object_attribute: 'name').first if a.nil? + n = a.value unless a.nil? + end + return n + end + end diff --git a/app/models/descriptor.rb b/app/models/descriptor.rb index 4a4885a0ee..c1718537c2 100644 --- a/app/models/descriptor.rb +++ b/app/models/descriptor.rb @@ -22,7 +22,7 @@ class Descriptor < ApplicationRecord acts_as_list scope: [:project_id] - ALTERNATE_VALUES_FOR = [:name, :short_name].freeze + ALTERNATE_VALUES_FOR = [:name, :short_name, :description_name, :key_name].freeze validates_presence_of :name, :type validate :type_is_subclassed @@ -41,6 +41,30 @@ def self.human_name self.name.demodulize.humanize end + ## retrunrs string, name of the descriptor in a particular language + # target: :key, :description, nil + def target_name(target, language_id) + n = self.name + a = nil + case target + when :key + n = self.key_name.nil? ? n : self.key_name + when :description + n = self.description_name.nil? ? n : self.description_name + end + unless language_id.nil? + case target + when :key + a = AlternateValue::Translation.where(alternate_value_object: self, language_id: language_id, alternate_value_object_attribute: 'key_name').first + when :description + a = AlternateValue::Translation.where(alternate_value_object: self, language_id: language_id, alternate_value_object_attribute: 'description_name').first + end + a = AlternateValue::Translation.where(alternate_value_object: self, language_id: language_id, alternate_value_object_attribute: 'name').first if a.nil? + n = a.value unless a.nil? + end + return n + end + def qualitative? type == 'Descriptor::Qualitative' end diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index 4f1e03e888..58eab5c6ac 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -209,7 +209,7 @@ def descriptors_hash_initiate h[d.id][:max] = -999999 if d.type == 'Descriptor::Continuous' || d.type == 'Descriptor::Sample' # max value used as continuous or sample h[d.id][:observations] = [] # all observation for a particular h[d.id][:observation_hash] = [] ### state_ids, true/false for a particular descriptor/otu_id/catalog_id combination (for PresenceAbsence or Qualitative or Continuous) - h[d.id][:status] = 'useful' ### 'used', 'useful', 'useless' + h[d.id][:status] = 'useless' ### 'used', 'useful', 'useless' end t = "'Observation::Continuous', 'Observation::PresenceAbsence', 'Observation::Qualitative', 'Observation::Sample'" @observation_matrix.observations.where('"observations"."type" IN (' + t + ')').each do |o| @@ -308,12 +308,14 @@ def eliminated_taxa def useful_descriptors list_of_remaining_taxa = {} + language = @language_id.blank? ? nil : @language_id.to_i @row_hash.each do |r_key, r_value| if r_value[:status] != 'eliminated' && d_value[:status] != 'used' list_of_remaining_taxa[r_value[:object_at_rank] ] = true end end number_of_taxa = list_of_remaining_taxa.count + array = [] @descriptors_hash.each do |d_key, d_value| d_value[:observations].each do |otu_key, otu_value| @@ -321,41 +323,119 @@ def useful_descriptors if @row_hash[otu_collection_object][:status] != 'eliminated' otu_value.each do |o| if o.character_state_id - d_key[:state_ids][o.character_state_id.to_s] = {} if d_key[:state_ids][o.character_state_id.to_s].nil? - d_key[:state_ids][o.character_state_id.to_s][:rows] = {} if d_key[:state_ids][o.character_state_id.to_s][:rows].nil? ## rows which this state identifies - d_key[:state_ids][o.character_state_id.to_s][:rows][ @row_hash[otu_collection_object][:object_at_rank] ] = true - d_key[:state_ids][o.character_state_id.to_s][:status] = 'useful' ## 'used', 'useful', 'useless' + d_value[:state_ids][o.character_state_id.to_s] = {} if d_value[:state_ids][o.character_state_id.to_s].nil? + d_value[:state_ids][o.character_state_id.to_s][:rows] = {} if d_value[:state_ids][o.character_state_id.to_s][:rows].nil? ## rows which this state identifies + d_value[:state_ids][o.character_state_id.to_s][:rows][ @row_hash[otu_collection_object][:object_at_rank] ] = true + d_value[:state_ids][o.character_state_id.to_s][:status] = 'useful' ## 'used', 'useful', 'useless' end unless o.presence.nil? - d_key[:state_ids][o.presence.to_s] = {} if d_key[:state_ids][o.presence.to_s].nil? - d_key[:state_ids][o.presence.to_s][:rows] = {} if d_key[:state_ids][o.presence.to_s][:rows].nil? ## rows which this state identifies - d_key[:state_ids][o.presence.to_s][:rows][ @row_hash[otu_collection_object][:object_at_rank] ] = true - d_key[:state_ids][o.presence.to_s][:status] = 'useful' ## 'used', 'useful', 'useless' + d_value[:state_ids][o.presence.to_s] = {} if d_value[:state_ids][o.presence.to_s].nil? + d_value[:state_ids][o.presence.to_s][:rows] = {} if d_value[:state_ids][o.presence.to_s][:rows].nil? ## rows which this state identifies + d_value[:state_ids][o.presence.to_s][:rows][ @row_hash[otu_collection_object][:object_at_rank] ] = true + d_value[:state_ids][o.presence.to_s][:status] = 'useful' ## 'used', 'useful', 'useless' + end + unless o.continuous_value.nil? + d_value[:state_ids][o.id] = true + end + unless o.sample_min.nil? + d_value[:state_ids][o.id] = {o_min: o.sample_min, o_max: o.sample_max} end - end end - end + descriptor = {} + descriptor[:id] = d_key + descriptor[:type] = d_value[:descriptor].type + descriptor[:name] = d_value[:descriptor].target_name(:key, language) + descriptor[:weight] = d_value[:descriptor].weight + descriptor[:position] = d_value[:descriptor].position + descriptor[:usefulness] = 0 + + sum = 0 + case d_value[:descriptor].type + when 'Descriptor::Qualitative' + number_of_states = d_value[:state_ids].count + descriptor[:states] = [] + d_value[:state_ids].each do |s_key, s_value| + c = CharacterState.find(s_key.to_i) + state = {} + state[:id] = c.id + state[:type] = c.type + state[:name] = c.target_name(:key, language) + state[:position] = c.position + state[:number_of_objects] = s_value[:rows].count + state[:status] = 'usefull' + n = s_value[:rows].count + if n == number_of_taxa || n == 0 + s_value[:status] = 'useless' + state[:status] = 'useless' + else + d_value[:status] = 'useful' + end + # weight = rem_taxa/number_of_states + squer (sum (rem_taxa/number_of_states - taxa_in_each_state)^2) + s += (number_of_taxa / number_of_states - s_value[:rows].count) ** 2 + descriptor[:states] += [state] + end + descriptor[:usefulness] = number_of_taxa / number_of_states + Math.sqrt(s) + descriptor[:states].sort_by!{|i| i.position} + when 'Descriptor::Continuous' + descriptor[:default_unit] = d_value[:descriptor].default_unit + descriptor[:min] = d_value[:min] + descriptor[:max] = d_value[:max] + number_of_measurements = d_value[:state_ids].count + s = (s_value[:o_min] - (s_value[:o_min] / 10)) / (d_value[:max] - d_value[:min]) + descriptor[:usefulness] = number_of_taxa * s * (2 - (number_of_measurements / number_of_taxa)) + when 'Descriptor::Sample' + descriptor[:default_unit] = d_value[:descriptor].default_unit + descriptor[:min] = d_value[:min] + descriptor[:max] = d_value[:max] + number_of_measurements = d_value[:state_ids].count + s = 0 + # i = max - min ; if 0 then (numMax - numMin / 10) + # sum of all i + # if numMax = numMin then numMax = numMax + 0.00001 + # weight = rem_taxa * (sum of i / number of measuments for taxon / (numMax - numMin) ) * (2 - number of measuments for taxon / rem_taxa) + d_value[:state_ids].each do |s_key, s_value| + if s_value[:o_min] == s_value[:o_max] || s_value[:o_max].blank? + s += (s_value[:o_max] - s_value[:o_min]) / number_of_measurements / (d_value[:max] - d_value[:min]) + else + s += (s_value[:o_min] - (s_value[:o_min] / 10)) / number_of_measurements / (d_value[:max] - d_value[:min]) + end + end + descriptor[:usefulness] = number_of_taxa * s * (2 - (number_of_measurements / number_of_taxa)) + + when 'Descriptor::PresenceAbsence' + number_of_states = 2 + descriptor[:states] = [] + d_value[:state_ids].each do |s_key, s_value| + c = CharacterState.find(s_key.to_i) + state = {} + state[:id] = c.id + state[:type] = c.type + state[:name] = s_key + state[:number_of_objects] = s_value[:rows].count + state[:status] = 'usefull' + n = s_value[:rows].count + if n == number_of_taxa || n == 0 + s_value[:status] = 'useless' + state[:status] = 'useless' + else + d_value[:status] = 'useful' + end + s += (number_of_taxa / number_of_states - s_value[:rows].count) ** 2 + descriptor[:states] += [state] + end + descriptor[:usefulness] = number_of_taxa / number_of_states + Math.sqrt(s) + descriptor[:states].sort_by!{|i| -i.name} + end - @row_hash.each do |r_key, r_value| - if r_value[:status] != 'eliminated' && d_value[:status] != 'used' - # not numeric - # weight = rem_taxa/number_of_states + squer (sum (rem_taxa/number_of_states - taxa_in_each_state)^2) - # numeric for each measurement for a particular species - # i = max - min ; if 0 then (numMax - numMin) / 10 - # sum of all i - # if numMax = numMin then numMax = numMax + 0.00001 - # weight = rem_taxa * (sum of i / number of measuments for taxon / (numMax - numMin) ) * (2 - number of measuments for taxon / rem_taxa) - end - end end end From 43ca6931be4cc18fe0218ce60079a58cc29d6125 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Mon, 14 Sep 2020 14:30:05 -0500 Subject: [PATCH 021/189] interactive key --- lib/interactive_key.rb | 44 ++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index 58eab5c6ac..ed3d9a30f2 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -55,13 +55,16 @@ class InteractiveKey attr_accessor :rows_with_filter #return the list of descriptors with selections - attr_accessor :used_descriptors + # attr_accessor :used_descriptors #return the list of useful descriptors - attr_accessor :useful_descriptors + # attr_accessor :useful_descriptors #return the list of descriptors not useful for identification - attr_accessor :not_useful_descriptors + # attr_accessor :not_useful_descriptors + + #return the list of descriptors and thair states + attr_accessor :list_of_descriptors #list of remaining rows attr_accessor :remaining @@ -104,9 +107,11 @@ def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, ke #main_logic @remaining = remaining_taxa @eliminated = eliminated_taxa - @useful_descriptors = useful_descriptors - @used_descriptors ### - @not_useful_descriptors #### + + @list_of_descriptors = useful_descriptors + # @useful_descriptors = useful_descriptors + # @used_descriptors ### + # @not_useful_descriptors #### @row_hash = nil @descriptors_hash = nil @@ -315,9 +320,10 @@ def useful_descriptors end end number_of_taxa = list_of_remaining_taxa.count - array = [] + array_of_descriptors = [] @descriptors_hash.each do |d_key, d_value| + taxa_with_unknown_character_states = list_of_remaining_taxa if @eliminate_unknown == 'false' d_value[:observations].each do |otu_key, otu_value| otu_collection_object = otu_key if @row_hash[otu_collection_object][:status] != 'eliminated' @@ -340,10 +346,13 @@ def useful_descriptors unless o.sample_min.nil? d_value[:state_ids][o.id] = {o_min: o.sample_min, o_max: o.sample_max} end + taxa_with_unknown_character_states[ @row_hash[otu_collection_object][:object_at_rank] ] = false end end end + number_of_taxa_with_unknown_character_states = taxa_with_unknown_character_states.select{|key, value| value == true}.count + descriptor = {} descriptor[:id] = d_key descriptor[:type] = d_value[:descriptor].type @@ -351,6 +360,7 @@ def useful_descriptors descriptor[:weight] = d_value[:descriptor].weight descriptor[:position] = d_value[:descriptor].position descriptor[:usefulness] = 0 + descriptor[:status] = d_value[:status] == 'used' ? 'used' : 'useless' sum = 0 case d_value[:descriptor].type @@ -364,7 +374,7 @@ def useful_descriptors state[:type] = c.type state[:name] = c.target_name(:key, language) state[:position] = c.position - state[:number_of_objects] = s_value[:rows].count + state[:number_of_objects] = s_value[:rows].count + number_of_taxa_with_unknown_character_states state[:status] = 'usefull' n = s_value[:rows].count if n == number_of_taxa || n == 0 @@ -372,6 +382,7 @@ def useful_descriptors state[:status] = 'useless' else d_value[:status] = 'useful' + descriptor[:status] = 'useful' end # weight = rem_taxa/number_of_states + squer (sum (rem_taxa/number_of_states - taxa_in_each_state)^2) s += (number_of_taxa / number_of_states - s_value[:rows].count) ** 2 @@ -414,7 +425,7 @@ def useful_descriptors state[:id] = c.id state[:type] = c.type state[:name] = s_key - state[:number_of_objects] = s_value[:rows].count + state[:number_of_objects] = s_value[:rows].count + number_of_taxa_with_unknown_character_states state[:status] = 'usefull' n = s_value[:rows].count if n == number_of_taxa || n == 0 @@ -430,13 +441,18 @@ def useful_descriptors descriptor[:states].sort_by!{|i| -i.name} end + array_of_descriptors += [descriptor] + end - - - - - + case @sorting + when 'ordered' + array_of_descriptors.sort_by!{|i| i[:position]} + when 'weighed' + array_of_descriptors.sort_by!{|i| [-i[:weight], i[:usefulness]] } + when 'optimized' + array_of_descriptors.sort_by!{|i| i[:usefulness]} end + end def observations From ae2fed4b9656fcdaffcb93177a91cb9671f6d8a3 Mon Sep 17 00:00:00 2001 From: jrflood Date: Tue, 15 Sep 2020 11:43:18 -0500 Subject: [PATCH 022/189] collection_objects api endpoint --- app/controllers/collection_objects_controller.rb | 2 +- app/controllers/sources_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/collection_objects_controller.rb b/app/controllers/collection_objects_controller.rb index a9dbcd8294..29a68c3cd1 100644 --- a/app/controllers/collection_objects_controller.rb +++ b/app/controllers/collection_objects_controller.rb @@ -32,7 +32,7 @@ def api_index # GET /api/v1/collection_objects/:id def api_show @collection_objects = CollectionObject.find(params[:id]) - render '/collection_objects/show.json.jbuilder' + render '/collection_objects/api/show.json.jbuilder' end def biocuration_classifications diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb index 44b3aecac5..7ee8a35ab9 100644 --- a/app/controllers/sources_controller.rb +++ b/app/controllers/sources_controller.rb @@ -31,7 +31,7 @@ def api_index # GET /api/v1/sources/:id def api_show @source = Source.find(params[:id]) - render '/sources/show.json.jbuilder' + render '/sources/api/show.json.jbuilder' end def list From 88157cb383185e62754a54608f7626820f17b17e Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Tue, 15 Sep 2020 17:11:10 -0500 Subject: [PATCH 023/189] interactive key --- .../interactive_key_controller.rb | 45 +++++++++++++++++-- db/schema.rb | 3 +- lib/interactive_key.rb | 43 +++++++++++++++--- 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/app/controllers/tasks/observation_matrices/interactive_key_controller.rb b/app/controllers/tasks/observation_matrices/interactive_key_controller.rb index d25911bc58..77b50f3c7a 100644 --- a/app/controllers/tasks/observation_matrices/interactive_key_controller.rb +++ b/app/controllers/tasks/observation_matrices/interactive_key_controller.rb @@ -1,11 +1,50 @@ class Tasks::ObservationMatrices::InteractiveKeyController < ApplicationController include TaskControllerConfiguration + include DataControllerConfiguration::ProjectDataControllerConfiguration - # GET + + #params[:observation_matrix_id, :project_id, :observation_matrix, :language_id, :keyword_ids, :row_filter, + # :sorting, :eliminate_unknown, :error_tolerance, :identified_to_rank, :selected_descriptors] def index + respond_to do |format| + format.html do + @observation_matrix = ObservationMatrix.where(project_id: sessions_current_project_id, id: params[:observation_matrix_id]).first unless params[:observation_matrix_id].blank? + # redirect_to new_observation_matrix_path and return if @observation_matrix.nil? + end + format.json { + @observation_matrix = InteractiveKey.new(filter_params) + } + end + end - @observation_matrix = ObservationMatrix.where(project_id: sessions_current_project_id, id: params[:observation_matrix_id]).first unless params[:observation_matrix_id].blank? -# redirect_to new_observation_matrix_path and return if @observation_matrix.nil? + def interactive_key_params + params.require(:observation_matrix).permit( + :observation_matrix_id, + :project_id, + :language_id, + :keyword_ids, + :row_filter, + :sorting, + :eliminate_unknown, + :error_tolerance, + :identified_to_rank, + :selected_descriptors + ) end + def filter_params + params.permit( + :observation_matrix_id, + :project_id, + :language_id, + :keyword_ids, + :row_filter, + :sorting, + :eliminate_unknown, + :error_tolerance, + :identified_to_rank, + :selected_descriptors + ) + end + end \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 8f2cfefd0e..85fdbb1b50 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_07_16_192152) do +ActiveRecord::Schema.define(version: 2020_09_01_142633) do # These are extensions that must be enabled in order to support this database enable_extension "fuzzystrmatch" @@ -162,6 +162,7 @@ t.integer "updated_by_id", null: false t.integer "project_id", null: false t.string "inverted_name" + t.text "definition" t.index ["created_by_id"], name: "bio_rel_created_by" t.index ["project_id"], name: "bio_rel_project" t.index ["updated_by_id"], name: "bio_rel_updated_by" diff --git a/lib/interactive_key.rb b/lib/interactive_key.rb index ed3d9a30f2..e787d6953f 100644 --- a/lib/interactive_key.rb +++ b/lib/interactive_key.rb @@ -113,8 +113,36 @@ def initialize(observation_matrix_id: nil, project_id: nil, language_id: nil, ke # @used_descriptors ### # @not_useful_descriptors #### - @row_hash = nil - @descriptors_hash = nil + @row_hash = nil + @descriptors_hash = nil + + end + + def self.interactive_key_hash + { + observation_matrix_id: @observation_matrix_id, + project_id: @project_id, +=begin + observation_matrix: @observation_matrix, + descriptor_available_languages: @descriptor_available_languages, + language_id: @language_id, + language_to_use: @language_to_use, + keyword_ids: @keyword_ids, + descriptor_available_keywords: @descriptor_available_keywords, + descriptors_with_filter: @descriptors_with_filter, + row_filter: @row_filter, + rows_with_filter: @rows_with_filter, + sorting: @sorting, + error_tolerance: @error_tolerance, + eliminate_unknown: @eliminate_unknown, + identified_to_rank: @identified_to_rank, + selected_descriptors: @selected_descriptors, + selected_descriptors_hash: @selected_descriptors_hash, + remaining: @remaining, + eliminated: @eliminated, + list_of_descriptors: @list_of_descriptors +=end + } end def observation_matrix @@ -122,7 +150,7 @@ def observation_matrix end def descriptors - if @sorting = 'weighted' + if @sorting == 'weighted' observation_matrix.descriptors.where('NOT descriptors.weight = 0 OR descriptors.weight IS NULL').order('descriptors.weight DESC, descriptors.position') else observation_matrix.descriptors.where('NOT descriptors.weight = 0 OR descriptors.weight IS NULL').order(:position) @@ -164,14 +192,15 @@ def descriptors_with_keywords def rows observation_matrix.reorder_rows(by = 'nomenclature') -# ObservationMatrixRow.where(observation_matrix_id: @observation_matrix_id) end def rows_with_filter if @row_item_filter rows else - rows.where('observation_matrix_rows.id IN (?)', @row_filter.to_s.split('|')) + #TODO does not works + rows + # rows.where('observation_matrix_rows.id IN (?)', @row_filter.to_s.split('|')) end end @@ -239,7 +268,7 @@ def descriptors_hash_initiate def selected_descriptors_hash_initiate # "123:1|3||125:3|5||135:2" h = {} - a = @selected_descriptors.split('||') + a = @selected_descriptors.to_s.split('||') a.each do |i| d = i.split(':') h[d[0]].to_i = d[1].split('|') @@ -281,7 +310,7 @@ def remaining_taxa @descriptors_hash[d_key][:observations][otu_collection_object].each do |o| p = true if o.sample_min <= d_min.to_i || o.sample_max >= d_max.to_i end - r_value[:errors] += 1 if p = false + r_value[:errors] += 1 if p == false r_value[:error_descriptors][@descriptors_hash[d_key][:descriptor]] = @descriptors_hash[d_key][:observations][otu_collection_object] end end From b52d3b8c017eda4f5ddaee14d9ff9b593851d8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Pereira?= Date: Tue, 15 Sep 2020 20:29:27 -0300 Subject: [PATCH 024/189] Added vue app for interactive keys --- .../tasks/matrix/observation_matrices.scss | 226 +++++------------- app/javascript/packs/application.js | 2 + .../vue/tasks/interactive_keys/app.vue | 51 ++++ .../components/DescriptorsView.vue | 10 + .../interactive_keys/components/MenuBar.vue | 62 +++++ .../components/TaxonNamesTree.vue | 16 ++ .../vue/tasks/interactive_keys/main.js | 19 ++ .../interactive_keys/request/resources.js | 10 + .../store/actions/actionNames.js | 6 + .../interactive_keys/store/actions/actions.js | 14 ++ .../store/actions/loadObservationMatrix.js | 13 + .../loadObservationMatrixDescriptors.js | 13 + .../store/getters/getObservationMatrix.js | 3 + .../getObservationMatrixDescriptors.js | 3 + .../store/getters/getSettings.js | 3 + .../interactive_keys/store/getters/getters.js | 20 ++ .../store/mutations/mutations.js | 20 ++ .../store/mutations/setObservationMatrix.js | 3 + .../setObservationMatrixDescriptors.js | 3 + .../store/mutations/setSettings.js | 3 + .../vue/tasks/interactive_keys/store/store.js | 32 +++ .../interactive_key/index.html.erb | 128 +--------- 22 files changed, 371 insertions(+), 289 deletions(-) create mode 100644 app/javascript/vue/tasks/interactive_keys/app.vue create mode 100644 app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue create mode 100644 app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue create mode 100644 app/javascript/vue/tasks/interactive_keys/components/TaxonNamesTree.vue create mode 100644 app/javascript/vue/tasks/interactive_keys/main.js create mode 100644 app/javascript/vue/tasks/interactive_keys/request/resources.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/actions/actionNames.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/actions/actions.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrixDescriptors.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrix.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrixDescriptors.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/getters/getSettings.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/getters/getters.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrix.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrixDescriptors.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/mutations/setSettings.js create mode 100644 app/javascript/vue/tasks/interactive_keys/store/store.js diff --git a/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss b/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss index b3d69d3fbc..d18a911fcf 100644 --- a/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss +++ b/app/assets/stylesheets/views/tasks/matrix/observation_matrices.scss @@ -24,170 +24,72 @@ text-align: left; } +#vue-interactive-keys { + height: calc(100vh - 220px); + max-height: calc(100vh - 220px); + + .header-bar { + width: 100%; + height: 50px; + border-bottom: 1px solid #CCCCCC; + background-color: white; + } -#header3i { - position: fixed; - width: 100%; - height: 56px; - top: 99px; - right: 0; - bottom: auto; - left: 0; - border-bottom: 2px solid #CCCCCC; - background-color: #C0C0B0; -} - -#header3i h1 -{ - margin: 0px; - font-size: 16pt; - font-weight: bold; - text-align: center; - font-family: arial,sans-serif; - color: #004050; -} - -#header3i table { - width: 100%; - background-color: #C0C0B0; - text-align: center; - color: #004050; -} - -#characters3i { - position: fixed; - top: 157px; - bottom: 45%; - left: 0px; - right: 0px; - margin: 0px 0px 0px 0px; - width: auto; - height: auto; - padding-left: 5px; - padding-right: 12px; - background-color: #CFCFBE; - border-bottom: 2px solid #CCCCCC; - overflow: auto; -} - -div.vertical #characters3i { - position: fixed; - top: 157px; - bottom: 42px; - left: 0px; - right: 50%; - margin: 0px 0px 0px 0px; - width: auto; - height: auto; - padding-left: 5px; - padding-right: 12px; - background-color: #CFCFBE; - border-bottom: 2px solid #CCCCCC; - overflow: auto; -} - -#characters3i h1, #content h2 { - color: #C00000; -} - -#taxa1_3i { - position: fixed; - top: 55%; - bottom: 42px; - margin: 0px 0px 0px 0px; - right: 50%; - left: 0px; - width: auto; - height: auto; - padding-left: 5px; - padding-right: 12px; - background-color: #C0C0B0; - border-bottom: 2px solid #CCCCCC; - overflow: auto; -} - -div.vertical #taxa1_3i { - position: fixed; - top: 157px; - bottom: 45%; - margin: 0px 0px 0px 0px; - right: 0px; - left: 50%; - width: auto; - height: auto; - padding-left: 5px; - padding-right: 12px; - background-color: #C0C0B0; - border-left: 2px solid #CCCCCC; - border-bottom: 2px solid #CCCCCC; - overflow: auto; -} - -#taxa2_3i { - position: fixed; - top: 55%; - bottom: 42px; - margin: 0px 0px 0px 0px; - width: auto; - height: auto; - left: 50%; - right: 0px; - padding-left: 5px; - padding-right: 12px; - background-color: #C0C0B0; - border-left: 2px solid #CCCCCC; - border-bottom: 2px solid #CCCCCC; - overflow: auto; -} - -.mainfont { color: #004050;} -.red { color: #C00000; } -.redbold { color: #C00000; font-weight: bold; } - -div.i3{ - color: #004050; - font-family: arial,sans-serif; -} - -div.i3 a { color: #004050;} -div.i3 a:visited { color: #004050;} -div.i3 a:hover { color: #C00000;} - -div.help3i -{ - background-color: #CAD9EE; - height: auto; - border: 1px solid; - padding: 1px; -} - -div.helpBox3i{ - background-color: #CAD9EE; - margin-left: 10px; - max-width: 300px; - position: absolute; - display: inline-block; - border: 1px solid; - z-index:10000; -} - -.a1 a, .a2 a, .a3 a, .a0 a { - text-decoration: none; -} + .i3-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(2, 1fr); + grid-column-gap: 0px; + grid-row-gap: 0px; + background-color: #CCCCCC; + grid-gap: 1px; + } + .grid-icon { + width: 20px; + height: 12px; + border: 2px solid transparent; + background-color: transparent; + grid-gap: 2px; + } + .grid-item { + background-color: white; + overflow: scroll; + } + + .layout-mode-1 { + .descriptors-view { + grid-area: 1 / 1 / 2 / 3; + } + .taxa-remaining { + grid-area: 2 / 1 / 3 / 2; + } + .taxa-eliminated { + grid-area: 2 / 2 / 3 / 3; + } + } + + .layout-mode-2 { + .descriptors-view { + grid-area: 1 / 1 / 3 / 2; + } + .taxa-remaining { + grid-area: 1 / 2 / 2 / 3; + } + .taxa-eliminated { + grid-area: 2 / 2 / 3 / 3; + } + } -.a1 { border:2px solid transparent; } -.a2 { border:2px outset #FFFFFF; cursor: hand; } -.a3 { border:2px inset #FFFFFF; } -.a0 { border:3px solid transparent;} -.a5 { border:3px outset #FFFFFF; cursor: hand; } -.a6 { border:3px inset #FFFFFF; } + .full-height { + height: 100%; + } -table.key { - background-color: #CAD9DD; - text-align: center; - color: #000080; -} + .mainfont { color: #004050;} + .red { color: #C00000; } + .redbold { color: #C00000; font-weight: bold; } -table.key td.taxon {text-align: left;} -table.key td.image {vertical-align: top;} + .i3 { + box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.2); + } +} \ No newline at end of file diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 205ba8bca3..590ccc9ba1 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -61,3 +61,5 @@ require('../vue/tasks/nomenclature/match/main.js') require('../vue/tasks/controlled_vocabularies/manage/main.js') require('../vue/tasks/collection_objects/match/main.js') require('../vue/tasks/sources/filter/main.js') +require('../vue/tasks/interactive_keys/main.js') + diff --git a/app/javascript/vue/tasks/interactive_keys/app.vue b/app/javascript/vue/tasks/interactive_keys/app.vue new file mode 100644 index 0000000000..72c953a57b --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/app.vue @@ -0,0 +1,51 @@ + + + diff --git a/app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue b/app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue new file mode 100644 index 0000000000..d97bca1680 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue @@ -0,0 +1,10 @@ + + + diff --git a/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue b/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue new file mode 100644 index 0000000000..c37dd2a9ab --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/app/javascript/vue/tasks/interactive_keys/components/TaxonNamesTree.vue b/app/javascript/vue/tasks/interactive_keys/components/TaxonNamesTree.vue new file mode 100644 index 0000000000..56e9f6d373 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/components/TaxonNamesTree.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/javascript/vue/tasks/interactive_keys/main.js b/app/javascript/vue/tasks/interactive_keys/main.js new file mode 100644 index 0000000000..1c42a0b494 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/main.js @@ -0,0 +1,19 @@ +import Vue from 'vue' +import App from './app.vue' +import { newStore } from './store/store' + +function init () { + new Vue({ + store: newStore(), + el: '#vue-interactive-keys', + render: function (createElement) { + return createElement(App) + } + }) +} + +document.addEventListener('turbolinks:load', (event) => { + if (document.querySelector('#vue-interactive-keys')) { + init() + } +}) \ No newline at end of file diff --git a/app/javascript/vue/tasks/interactive_keys/request/resources.js b/app/javascript/vue/tasks/interactive_keys/request/resources.js new file mode 100644 index 0000000000..b27eb1d20f --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/request/resources.js @@ -0,0 +1,10 @@ +import ajaxCall from 'helpers/ajaxCall' + +const GetObservationMatrix = (id) => ajaxCall('get', `/observation_matrices/${id}.json`) + +const GetMatrixObservationColumns = (id, params) => ajaxCall('get', `/observation_matrices/${id}/observation_matrix_columns.json`, { params: params }) + +export { + GetObservationMatrix, + GetMatrixObservationColumns +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/actions/actionNames.js b/app/javascript/vue/tasks/interactive_keys/store/actions/actionNames.js new file mode 100644 index 0000000000..b0b450f043 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/actions/actionNames.js @@ -0,0 +1,6 @@ +const ActionNames = { + LoadObservationMatrix: 'loadObservationMatrix', + LoadObservationMatrixDescriptors: 'loadObservationMatrixDescriptors' +} + +export default ActionNames diff --git a/app/javascript/vue/tasks/interactive_keys/store/actions/actions.js b/app/javascript/vue/tasks/interactive_keys/store/actions/actions.js new file mode 100644 index 0000000000..a70d20b560 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/actions/actions.js @@ -0,0 +1,14 @@ +import ActionNames from './actionNames' + +import loadObservationMatrix from './loadObservationMatrix' +import loadObservationMatrixDescriptors from './loadObservationMatrixDescriptors' + +const ActionFunctions = { + [ActionNames.LoadObservationMatrix]: loadObservationMatrix, + [ActionNames.LoadObservationMatrixDescriptors]: loadObservationMatrixDescriptors +} + +export { + ActionNames, + ActionFunctions +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js b/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js new file mode 100644 index 0000000000..daf6e0074b --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js @@ -0,0 +1,13 @@ +import { GetObservationMatrix } from '../../request/resources' +import { MutationNames } from '../mutations/mutations' + +export default ({ commit }, id) => { + return new Promise((resolve, reject) => { + GetObservationMatrix(id).then(response => { + commit(MutationNames.SetObservationMatrix, response.body) + resolve(response) + }, error => { + reject(error) + }) + }) +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrixDescriptors.js b/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrixDescriptors.js new file mode 100644 index 0000000000..f0ea194e68 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrixDescriptors.js @@ -0,0 +1,13 @@ +import { GetMatrixObservationColumns } from '../../request/resources' +import { MutationNames } from '../mutations/mutations' + +export default ({ commit }, matrixId) => { + return new Promise((resolve, reject) => { + GetMatrixObservationColumns(matrixId).then(response => { + commit(MutationNames.SetObservationMatrixDescriptors, response.body) + resolve(response) + }, error => { + reject(error) + }) + }) +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrix.js b/app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrix.js new file mode 100644 index 0000000000..4cb51edbe3 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrix.js @@ -0,0 +1,3 @@ +export default (state) => { + return state.observationMatrix +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrixDescriptors.js b/app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrixDescriptors.js new file mode 100644 index 0000000000..970860f325 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/getters/getObservationMatrixDescriptors.js @@ -0,0 +1,3 @@ +export default (state) => { + return state.observationMatrixDescriptors +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/getters/getSettings.js b/app/javascript/vue/tasks/interactive_keys/store/getters/getSettings.js new file mode 100644 index 0000000000..f75ef3e6d8 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/getters/getSettings.js @@ -0,0 +1,3 @@ +export default (state) => { + return state.settings +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/getters/getters.js b/app/javascript/vue/tasks/interactive_keys/store/getters/getters.js new file mode 100644 index 0000000000..f481e6c00c --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/getters/getters.js @@ -0,0 +1,20 @@ +import getObservationMatrix from './getObservationMatrix' +import getObservationMatrixDescriptors from './getObservationMatrixDescriptors' +import getSettings from './getSettings' + +const GetterNames = { + GetObservationMatrix: 'getObservationMatrix', + GetObservationMatrixDescriptors: 'getObservationMatrixDescriptors', + GetSettings: 'getSettings' +} + +const GetterFunctions = { + [GetterNames.GetObservationMatrix]: getObservationMatrix, + [GetterNames.GetObservationMatrixDescriptors]: getObservationMatrixDescriptors, + [GetterNames.GetSettings]: getSettings +} + +export { + GetterNames, + GetterFunctions +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js b/app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js new file mode 100644 index 0000000000..68bf4b5f55 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js @@ -0,0 +1,20 @@ +import setObservationMatrix from './setObservationMatrix' +import setObservationMatrixDescriptors from './setObservationMatrixDescriptors' +import setSettings from './setSettings' + +const MutationNames = { + SetObservationMatrix: 'setObsrvationMatrix', + SetObservationMatrixDescriptors: 'setObservationMatrixDescriptors', + SetSettings: 'setSettings' +} + +const MutationFunctions = { + [MutationNames.SetObservationMatrix]: setObservationMatrix, + [MutationNames.SetObservationMatrixDescriptors]: setObservationMatrixDescriptors, + [MutationNames.SetSettings]: setSettings +} + +export { + MutationNames, + MutationFunctions +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrix.js b/app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrix.js new file mode 100644 index 0000000000..47084ea8e6 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrix.js @@ -0,0 +1,3 @@ +export default (state, value) => { + state.observationMatrix = value +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrixDescriptors.js b/app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrixDescriptors.js new file mode 100644 index 0000000000..ed823445c5 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/mutations/setObservationMatrixDescriptors.js @@ -0,0 +1,3 @@ +export default (state, value) => { + state.observationMatrixDescriptors = value +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/mutations/setSettings.js b/app/javascript/vue/tasks/interactive_keys/store/mutations/setSettings.js new file mode 100644 index 0000000000..55f32f60a8 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/mutations/setSettings.js @@ -0,0 +1,3 @@ +export default (state, value) => { + state.settings = value +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/store.js b/app/javascript/vue/tasks/interactive_keys/store/store.js new file mode 100644 index 0000000000..255125b5e1 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/store.js @@ -0,0 +1,32 @@ +import Vue from 'vue' +import Vuex from 'vuex' + +import { GetterFunctions } from './getters/getters' +import { MutationFunctions } from './mutations/mutations' +import { ActionFunctions } from './actions/actions' + +Vue.use(Vuex) + +function makeInitialState () { + return { + settings: { + gridLayout: 'layout-mode-1' + }, + observationMatrix: undefined, + observationMatrixDescriptors: [] + } +} + +function newStore () { + return new Vuex.Store({ + state: makeInitialState(), + getters: GetterFunctions, + mutations: MutationFunctions, + actions: ActionFunctions + }) +} + +export { + newStore, + makeInitialState +} diff --git a/app/views/tasks/observation_matrices/interactive_key/index.html.erb b/app/views/tasks/observation_matrices/interactive_key/index.html.erb index f2d1b483c7..6a90855999 100644 --- a/app/views/tasks/observation_matrices/interactive_key/index.html.erb +++ b/app/views/tasks/observation_matrices/interactive_key/index.html.erb @@ -1,127 +1 @@ -

    Interactive key

    - -
    - - -
    - <%= content_tag(:h1, observation_matrix_tag(@observation_matrix), id: 'ltrSecondHeader') -%> - -
    -
    -
    -
    -

    Remaining Taxa

    -
    -
    -

    Elimitated Taxa

    -
    -
    - - - - -
    - \ No newline at end of file +
    \ No newline at end of file From 1d865f69e92ec339be293fcb490604e280fa6db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Pereira?= Date: Tue, 15 Sep 2020 20:42:48 -0300 Subject: [PATCH 025/189] Added autocomplete --- .../interactive_keys/components/MenuBar.vue | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue b/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue index c37dd2a9ab..22e9d1ef6a 100644 --- a/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue +++ b/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue @@ -1,7 +1,17 @@ \ No newline at end of file diff --git a/app/javascript/vue/tasks/interactive_keys/components/Remaining.vue b/app/javascript/vue/tasks/interactive_keys/components/Remaining.vue new file mode 100644 index 0000000000..f2bce4875c --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/components/Remaining.vue @@ -0,0 +1,25 @@ + + + diff --git a/app/javascript/vue/tasks/interactive_keys/components/TaxonNamesTree.vue b/app/javascript/vue/tasks/interactive_keys/components/TaxonNamesTree.vue deleted file mode 100644 index 56e9f6d373..0000000000 --- a/app/javascript/vue/tasks/interactive_keys/components/TaxonNamesTree.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/app/javascript/vue/tasks/interactive_keys/components/extendResult.js b/app/javascript/vue/tasks/interactive_keys/components/extendResult.js new file mode 100644 index 0000000000..ebe6643916 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/components/extendResult.js @@ -0,0 +1,9 @@ +import { GetterNames } from '../store/getters/getters' + +export default { + computed: { + observationMatrix () { + return this.$store.getters[GetterNames.GetObservationMatrix] + } + } +} From 547a9aebc38565609f732859500cf67aa3fc9718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Pereira?= Date: Mon, 28 Sep 2020 16:30:36 -0300 Subject: [PATCH 060/189] Filter descriptors --- .../components/DescriptorsView.vue | 58 +++++++++++++++---- .../interactive_keys/components/MenuBar.vue | 2 +- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue b/app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue index f39e7ac035..5313fe8111 100644 --- a/app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue +++ b/app/javascript/vue/tasks/interactive_keys/components/DescriptorsView.vue @@ -1,15 +1,44 @@ @@ -34,6 +63,15 @@ export default { descriptors () { return this.$store.getters[GetterNames.GetObservationMatrix] ? this.$store.getters[GetterNames.GetObservationMatrix].list_of_descriptors : [] }, + descriptorsUsed () { + return this.descriptors.filter(d => d.status === 'used') + }, + descriptorsUseless () { + return this.descriptors.filter(d => d.status === 'useless') + }, + descriptorsUseful () { + return this.descriptors.filter(d => d.status === 'useful') + }, filter: { get () { return this.$store.getters[GetterNames.GetDescriptorsFilter] diff --git a/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue b/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue index 6d546ec60e..58338aaf2e 100644 --- a/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue +++ b/app/javascript/vue/tasks/interactive_keys/components/MenuBar.vue @@ -18,7 +18,7 @@ type="button" class="button normal-input button-default" @click="loadMatrix(observationMatrix.observation_matrix_id)"> - Process + Proceed
    -
    +
    + @@ -48,6 +52,8 @@ import NavComponent from 'components/navBar' import Autocomplete from 'components/autocomplete' import SetParam from 'helpers/setParam' +import SortingComponent from './Filters/Sorting.vue' +import IdentifierRank from './Filters/IdentifierRank' import { GetterNames } from '../store/getters/getters' import { MutationNames } from '../store/mutations/mutations' import { ActionNames } from '../store/actions/actions' @@ -55,7 +61,9 @@ import { ActionNames } from '../store/actions/actions' export default { components: { NavComponent, - Autocomplete + Autocomplete, + IdentifierRank, + SortingComponent }, computed: { observationMatrix () { diff --git a/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js b/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js index 46368b8809..a397d8291c 100644 --- a/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js +++ b/app/javascript/vue/tasks/interactive_keys/store/actions/loadObservationMatrix.js @@ -3,7 +3,7 @@ import { MutationNames } from '../mutations/mutations' import { GetterNames } from '../getters/getters' export default ({ commit, getters, state }, id) => { - const filters = { selected_descriptors: getters[GetterNames.GetFilter] } + const filters = getters[GetterNames.GetFilter] return new Promise((resolve, reject) => { state.settings.isLoading = true GetInteractiveKey(id, filters).then(response => { diff --git a/app/javascript/vue/tasks/interactive_keys/store/actions/loadUpdatedRemaining.js b/app/javascript/vue/tasks/interactive_keys/store/actions/loadUpdatedRemaining.js index 448e2617a6..8ebc719636 100644 --- a/app/javascript/vue/tasks/interactive_keys/store/actions/loadUpdatedRemaining.js +++ b/app/javascript/vue/tasks/interactive_keys/store/actions/loadUpdatedRemaining.js @@ -3,7 +3,7 @@ import { MutationNames } from '../mutations/mutations' import { GetterNames } from '../getters/getters' export default ({ commit, getters, state }) => { - const filters = { selected_descriptors: getters[GetterNames.GetFilter] } + const filters = getters[GetterNames.GetFilter] return new Promise((resolve, reject) => { state.settings.isLoading = true GetInteractiveKey(state.observationMatrix.observation_matrix_id, filters).then(response => { diff --git a/app/javascript/vue/tasks/interactive_keys/store/getters/getFilter.js b/app/javascript/vue/tasks/interactive_keys/store/getters/getFilter.js index 2b4b1578ec..df43b48de0 100644 --- a/app/javascript/vue/tasks/interactive_keys/store/getters/getFilter.js +++ b/app/javascript/vue/tasks/interactive_keys/store/getters/getFilter.js @@ -1 +1,4 @@ -export default state => Object.entries(state.descriptorsFilter).filter(d => d[1]).map(descriptor => descriptor.join(':')).join('||') +export default state => { + const filterDescriptors = Object.entries(state.descriptorsFilter).filter(d => d[1]).map(descriptor => descriptor.join(':')).join('||') || undefined + return Object.assign({}, { selected_descriptors: filterDescriptors }, state.filters) +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/getters/getParamsFilter.js b/app/javascript/vue/tasks/interactive_keys/store/getters/getParamsFilter.js new file mode 100644 index 0000000000..298d6503ae --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/getters/getParamsFilter.js @@ -0,0 +1 @@ +export default state => state.filters diff --git a/app/javascript/vue/tasks/interactive_keys/store/getters/getters.js b/app/javascript/vue/tasks/interactive_keys/store/getters/getters.js index 95dda42953..f73c51a0bc 100644 --- a/app/javascript/vue/tasks/interactive_keys/store/getters/getters.js +++ b/app/javascript/vue/tasks/interactive_keys/store/getters/getters.js @@ -3,13 +3,15 @@ import getObservationMatrix from './getObservationMatrix' import getObservationMatrixDescriptors from './getObservationMatrixDescriptors' import getSettings from './getSettings' import getFilter from './getFilter' +import getParamsFilter from './getParamsFilter' const GetterNames = { GetDescriptorsFilter: 'getDescriptorsFilter', GetObservationMatrix: 'getObservationMatrix', GetObservationMatrixDescriptors: 'getObservationMatrixDescriptors', GetSettings: 'getSettings', - GetFilter: 'getFilter' + GetFilter: 'getFilter', + GetParamsFilter: 'getParamsFilter' } const GetterFunctions = { @@ -17,7 +19,8 @@ const GetterFunctions = { [GetterNames.GetObservationMatrix]: getObservationMatrix, [GetterNames.GetObservationMatrixDescriptors]: getObservationMatrixDescriptors, [GetterNames.GetSettings]: getSettings, - [GetterNames.GetFilter]: getFilter + [GetterNames.GetFilter]: getFilter, + [GetterNames.GetParamsFilter]: getParamsFilter } export { diff --git a/app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js b/app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js index 7dc0a742f5..9b1692bb22 100644 --- a/app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js +++ b/app/javascript/vue/tasks/interactive_keys/store/mutations/mutations.js @@ -2,19 +2,22 @@ import setObservationMatrix from './setObservationMatrix' import setObservationMatrixDescriptors from './setObservationMatrixDescriptors' import setSettings from './setSettings' import setDescriptorsFilter from './setDescriptorsFilter' +import setParamsFilter from './setParamsFilter' const MutationNames = { SetDescriptorsFilter: 'setDescriptorsFilter', SetObservationMatrix: 'setObsrvationMatrix', SetObservationMatrixDescriptors: 'setObservationMatrixDescriptors', - SetSettings: 'setSettings' + SetSettings: 'setSettings', + SetParamsFilter: 'setParamsFilter' } const MutationFunctions = { [MutationNames.SetDescriptorsFilter]: setDescriptorsFilter, [MutationNames.SetObservationMatrix]: setObservationMatrix, [MutationNames.SetObservationMatrixDescriptors]: setObservationMatrixDescriptors, - [MutationNames.SetSettings]: setSettings + [MutationNames.SetSettings]: setSettings, + [MutationNames.SetParamsFilter]: setParamsFilter } export { diff --git a/app/javascript/vue/tasks/interactive_keys/store/mutations/setParamsFilter.js b/app/javascript/vue/tasks/interactive_keys/store/mutations/setParamsFilter.js new file mode 100644 index 0000000000..ba14681d80 --- /dev/null +++ b/app/javascript/vue/tasks/interactive_keys/store/mutations/setParamsFilter.js @@ -0,0 +1,3 @@ +export default (state, value) => { + state.filters = value +} diff --git a/app/javascript/vue/tasks/interactive_keys/store/store.js b/app/javascript/vue/tasks/interactive_keys/store/store.js index eb5cee802a..4858026283 100644 --- a/app/javascript/vue/tasks/interactive_keys/store/store.js +++ b/app/javascript/vue/tasks/interactive_keys/store/store.js @@ -15,7 +15,11 @@ function makeInitialState () { }, observationMatrix: undefined, observationMatrixDescriptors: [], - descriptorsFilter: {} + descriptorsFilter: {}, + filters: { + identified_to_rank: undefined, + sorting: undefined + } } } From e15477c557ad6bd9fffd52eca766e10c51db5932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Pereira?= Date: Tue, 6 Oct 2020 11:55:31 -0300 Subject: [PATCH 086/189] Tweak --- .../interactive_keys/components/Filters/IdentifierRank.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/vue/tasks/interactive_keys/components/Filters/IdentifierRank.vue b/app/javascript/vue/tasks/interactive_keys/components/Filters/IdentifierRank.vue index 4bcda17734..999040ebb0 100644 --- a/app/javascript/vue/tasks/interactive_keys/components/Filters/IdentifierRank.vue +++ b/app/javascript/vue/tasks/interactive_keys/components/Filters/IdentifierRank.vue @@ -1,6 +1,6 @@