diff --git a/.gitignore b/.gitignore
index e5eb8ea5bd..ab0ea98b5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ node_modules
/config/credentials/test.key
/config/credentials/staging.key
/config/credentials/production.key
+/config/credentials/appliance.key
/app/assets/builds/*
!/app/assets/builds/.keep
diff --git a/Gemfile b/Gemfile
index 215fecf35e..c423cef31f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -68,9 +68,16 @@ gem 'recaptcha', '~> 5.9.0'
gem 'rest-client'
gem 'rexml', '~> 3'
gem 'stackprof', require: false
+
+# pinning strscan to v 3.0.1 to deal with deployment issue. Remove line below when issue is fixed
+gem 'strscan', '3.0.1'
+
gem 'terser'
gem 'thin'
gem 'will_paginate', '~> 3.0'
+gem 'net-ftp'
+gem 'flag-icons-rails', '~> 3.4'
+gem 'inline_svg'
group :staging, :production do
# Application monitoring
diff --git a/Gemfile.lock b/Gemfile.lock
index bcd80c4489..a577448127 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -82,29 +82,33 @@ GEM
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
- addressable (2.8.5)
- public_suffix (>= 2.0.2, < 6.0)
- airbrussh (1.5.0)
+ addressable (2.8.7)
+ public_suffix (>= 2.0.2, < 7.0)
+ airbrussh (1.5.3)
sshkit (>= 1.6.1, != 1.7.0)
ast (2.4.2)
- autoprefixer-rails (10.4.16.0)
+ autoprefixer-rails (10.4.19.0)
execjs (~> 2)
base64 (0.1.0)
- bcrypt_pbkdf (1.1.0)
- bootsnap (1.17.1)
+ bcrypt_pbkdf (1.1.1)
+ bcrypt_pbkdf (1.1.1-arm64-darwin)
+ bcrypt_pbkdf (1.1.1-x86_64-darwin)
+ bigdecimal (3.1.8)
+ bootsnap (1.18.4)
msgpack (~> 1.2)
bootstrap (5.2.3)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 2.11.6, < 3)
sassc-rails (>= 2.0.0)
- brakeman (6.0.1)
- builder (3.2.4)
- capistrano (3.18.0)
+ brakeman (6.2.1)
+ racc
+ builder (3.3.0)
+ capistrano (3.19.1)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
- capistrano-bundler (2.1.0)
+ capistrano-bundler (2.1.1)
capistrano (~> 3.1)
capistrano-locally (0.3.0)
capistrano (~> 3.0)
@@ -118,11 +122,11 @@ GEM
sshkit (~> 1.3)
capistrano-yarn (2.0.2)
capistrano (~> 3.0)
- capybara (3.39.2)
+ capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
- nokogiri (~> 1.8)
+ nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
@@ -130,41 +134,46 @@ GEM
chart-js-rails (0.1.7)
railties (> 3.1)
coderay (1.1.3)
- concurrent-ruby (1.2.3)
+ concurrent-ruby (1.3.4)
crass (1.0.6)
cube-ruby (0.0.3)
daemons (1.4.1)
- dalli (3.2.6)
+ dalli (3.2.8)
date (3.3.4)
- debug (1.9.1)
+ debug (1.9.2)
irb (~> 1.10)
reline (>= 0.3.8)
- diff-lcs (1.5.0)
- domain_name (0.6.20231109)
+ diff-lcs (1.5.1)
+ domain_name (0.6.20240107)
ed25519 (1.3.0)
- erubi (1.12.0)
+ erubi (1.13.0)
erubis (2.7.0)
eventmachine (1.2.7)
- excon (0.108.0)
+ excon (0.111.0)
execjs (2.9.1)
- faraday (2.7.12)
- base64
- faraday-net_http (>= 2.0, < 3.1)
- ruby2_keywords (>= 0.0.4)
+ faraday (2.11.0)
+ faraday-net_http (>= 2.0, < 3.4)
+ logger
faraday-excon (2.1.0)
excon (>= 0.27.4)
faraday (~> 2.0)
faraday-multipart (1.0.4)
multipart-post (~> 2)
- faraday-net_http (3.0.2)
- ffi (1.16.3)
+ faraday-net_http (3.3.0)
+ net-http
+ ffi (1.17.0)
+ ffi (1.17.0-arm64-darwin)
+ ffi (1.17.0-x86_64-darwin)
+ flag-icons-rails (3.4.6.1)
+ sass-rails
flamegraph (0.9.5)
globalid (1.2.1)
activesupport (>= 6.1)
- graphql (2.0.27)
- graphql-client (0.18.0)
+ graphql (2.0.31)
+ base64
+ graphql-client (0.23.0)
activesupport (>= 3.0)
- graphql
+ graphql (>= 1.13.0)
haml (5.2.2)
temple (>= 0.8.0)
tilt
@@ -174,28 +183,32 @@ GEM
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
http-accept (1.7.0)
- http-cookie (1.0.5)
+ http-cookie (1.0.7)
domain_name (~> 0.5)
- i18n (1.14.1)
+ i18n (1.14.5)
concurrent-ruby (~> 1.0)
+ inline_svg (1.10.0)
+ activesupport (>= 3.0)
+ nokogiri (>= 1.6)
io-console (0.7.2)
- irb (1.12.0)
- rdoc
+ irb (1.14.0)
+ rdoc (>= 4.0.0)
reline (>= 0.4.2)
iso-639 (0.3.6)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- jquery-ui-rails (6.0.1)
+ jquery-ui-rails (7.0.0)
railties (>= 3.2.16)
- jsbundling-rails (1.3.0)
+ jsbundling-rails (1.3.1)
railties (>= 6.0.0)
json (2.7.2)
language_server-protocol (3.17.0.3)
- listen (3.8.0)
+ listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
+ logger (1.6.1)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
@@ -205,19 +218,24 @@ GEM
net-imap
net-pop
net-smtp
- marcel (1.0.2)
+ marcel (1.0.4)
matrix (0.4.2)
- method_source (1.0.0)
- mime-types (3.5.1)
+ method_source (1.1.0)
+ mime-types (3.5.2)
mime-types-data (~> 3.2015)
- mime-types-data (3.2023.1003)
+ mime-types-data (3.2024.0903)
mini_mime (1.1.5)
- minitest (5.21.2)
+ minitest (5.25.1)
msgpack (1.7.2)
multi_json (1.15.0)
- multipart-post (2.3.0)
+ multipart-post (2.4.1)
mysql2 (0.5.5)
- net-imap (0.4.7)
+ net-ftp (0.3.7)
+ net-protocol
+ time
+ net-http (0.4.1)
+ uri
+ net-imap (0.4.16)
date
net-protocol
net-pop (0.1.2)
@@ -226,23 +244,27 @@ GEM
timeout
net-scp (4.0.0)
net-ssh (>= 2.6.5, < 8.0.0)
- net-smtp (0.4.0)
+ net-sftp (4.0.0)
+ net-ssh (>= 5.0.0, < 8.0.0)
+ net-smtp (0.5.0)
net-protocol
- net-ssh (7.2.0)
+ net-ssh (7.2.3)
netrc (0.11.0)
- newrelic_rpm (9.6.0)
- base64
- nio4r (2.6.1)
- nokogiri (1.16.0-arm64-darwin)
+ newrelic_rpm (9.13.0)
+ nio4r (2.7.3)
+ nokogiri (1.16.7-arm64-darwin)
racc (~> 1.4)
- nokogiri (1.16.0-x86_64-darwin)
+ nokogiri (1.16.7-x86_64-darwin)
racc (~> 1.4)
- nokogiri (1.16.0-x86_64-linux)
+ nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
- oj (3.16.1)
+ oj (3.16.5)
+ bigdecimal (>= 3.0)
+ ostruct (>= 0.2)
open_uri_redirections (0.2.1)
- parallel (1.24.0)
- parser (3.3.0.5)
+ ostruct (0.6.0)
+ parallel (1.26.3)
+ parser (3.3.5.0)
ast (~> 2.4.1)
racc
popper_js (2.11.8)
@@ -250,10 +272,10 @@ GEM
coderay (~> 1.1)
method_source (~> 1.0)
psych (3.3.4)
- public_suffix (5.0.4)
- racc (1.7.3)
- rack (2.2.8)
- rack-mini-profiler (3.1.1)
+ public_suffix (6.0.1)
+ racc (1.8.1)
+ rack (2.2.9)
+ rack-mini-profiler (3.3.1)
rack (>= 1.2.0)
rack-test (2.1.0)
rack (>= 1.3)
@@ -292,55 +314,56 @@ GEM
rainbow (3.1.1)
rake (13.2.1)
rb-fsevent (0.11.2)
- rb-inotify (0.10.1)
+ rb-inotify (0.11.1)
ffi (~> 1.0)
rdoc (6.3.4.1)
recaptcha (5.9.0)
json
redis (4.8.1)
- regexp_parser (2.9.0)
- reline (0.5.0)
+ regexp_parser (2.9.2)
+ reline (0.5.9)
io-console (~> 0.5)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
- rexml (3.2.6)
- rspec-core (3.12.2)
- rspec-support (~> 3.12.0)
- rspec-expectations (3.12.3)
+ rexml (3.3.7)
+ rspec-core (3.13.1)
+ rspec-support (~> 3.13.0)
+ rspec-expectations (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.12.0)
- rspec-mocks (3.12.6)
+ rspec-support (~> 3.13.0)
+ rspec-mocks (3.13.1)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.12.0)
- rspec-rails (6.1.0)
- actionpack (>= 6.1)
- activesupport (>= 6.1)
- railties (>= 6.1)
- rspec-core (~> 3.12)
- rspec-expectations (~> 3.12)
- rspec-mocks (~> 3.12)
- rspec-support (~> 3.12)
- rspec-support (3.12.1)
- rubocop (1.63.3)
+ rspec-support (~> 3.13.0)
+ rspec-rails (7.0.1)
+ actionpack (>= 7.0)
+ activesupport (>= 7.0)
+ railties (>= 7.0)
+ rspec-core (~> 3.13)
+ rspec-expectations (~> 3.13)
+ rspec-mocks (~> 3.13)
+ rspec-support (~> 3.13)
+ rspec-support (3.13.1)
+ rubocop (1.66.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 1.8, < 3.0)
- rexml (>= 3.2.5, < 4.0)
- rubocop-ast (>= 1.31.1, < 2.0)
+ regexp_parser (>= 2.4, < 3.0)
+ rubocop-ast (>= 1.32.2, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
- rubocop-ast (1.31.2)
- parser (>= 3.3.0.4)
+ rubocop-ast (1.32.3)
+ parser (>= 3.3.1.0)
ruby-progressbar (1.13.0)
- ruby2_keywords (0.0.5)
- ruby_parser (3.20.3)
+ ruby_parser (3.21.1)
+ racc (~> 1.5)
sexp_processor (~> 4.16)
+ sass-rails (6.0.0)
+ sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
@@ -354,40 +377,46 @@ GEM
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
- sprockets-rails (3.4.2)
- actionpack (>= 5.2)
- activesupport (>= 5.2)
+ sprockets-rails (3.5.2)
+ actionpack (>= 6.1)
+ activesupport (>= 6.1)
sprockets (>= 3.0.0)
- sshkit (1.21.6)
+ sshkit (1.23.0)
+ base64
net-scp (>= 1.1.2)
+ net-sftp (>= 2.1.2)
net-ssh (>= 2.8.0)
- stackprof (0.2.25)
- stimulus-rails (1.3.3)
+ stackprof (0.2.26)
+ stimulus-rails (1.3.4)
railties (>= 6.0.0)
+ strscan (3.0.1)
temple (0.10.3)
- terser (1.1.20)
+ terser (1.2.3)
execjs (>= 0.3.0, < 3)
thin (1.8.2)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
- thor (1.3.0)
- tilt (2.3.0)
+ thor (1.3.2)
+ tilt (2.4.0)
+ time (0.3.0)
+ date
timeout (0.4.1)
- turbo-rails (1.5.0)
+ turbo-rails (2.0.6)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
+ uri (0.13.1)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
will_paginate (3.3.1)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.6.12)
+ zeitwerk (2.6.18)
PLATFORMS
arm64-darwin-22
@@ -414,12 +443,14 @@ DEPENDENCIES
dalli
debug
ed25519 (>= 1.2, < 2.0)
+ flag-icons-rails (~> 3.4)
flamegraph
graphql (~> 2.0.27)
graphql-client
haml (~> 5.1)
html2haml
i18n
+ inline_svg
iso-639 (~> 0.3.6)
jquery-rails
jquery-ui-rails
@@ -427,6 +458,7 @@ DEPENDENCIES
listen
multi_json
mysql2 (= 0.5.5)
+ net-ftp
newrelic_rpm
oj
ontologies_api_client!
@@ -448,6 +480,7 @@ DEPENDENCIES
sprockets-rails
stackprof
stimulus-rails
+ strscan (= 3.0.1)
terser
thin
turbo-rails
@@ -455,4 +488,4 @@ DEPENDENCIES
will_paginate (~> 3.0)
BUNDLED WITH
- 2.4.19
+ 2.5.11
diff --git a/app/assets/javascripts/bp_class_tree.js.erb b/app/assets/javascripts/bp_class_tree.js.erb
index e3cbbc8c95..74c7e9f622 100644
--- a/app/assets/javascripts/bp_class_tree.js.erb
+++ b/app/assets/javascripts/bp_class_tree.js.erb
@@ -86,7 +86,7 @@ function initClassTree() {
});
};
-function nodeClicked(node_id) {
+function nodeClicked(node_id, lang = "en") {
// Get current html and store data in cache (to account for changes since the cache was retrieved)
setCacheCurrent();
@@ -128,12 +128,12 @@ function nodeClicked(node_id) {
// Insert notes table
insertNotesTable(tabData["notes_table_data"]);
-
wrapupTabChange(selectedTab);
} else {
jQuery.blockUI({ message: '
' + '<%= image_tag src="jquery.simple.tree/spinner.gif" %>' + ' Loading Class...
', showOverlay: false });
- jQuery.get('/ajax_concepts/'+jQuery(document).data().bp.ont_viewer.ontology_id+'/?conceptid='+node_id+'&callback=load',
- function(data){
+ var ajaxUrl = '/ajax_concepts/'+jQuery(document).data().bp.ont_viewer.ontology_id+'/?conceptid='+node_id+'&lang=' + lang + '&callback=load'
+ jQuery.get(ajaxUrl,
+ function(data) {
var tabData = data.split("|||");
// the tabs
@@ -181,14 +181,16 @@ function placeTreeView(treeHTML) {
}
// Retrieve the tree view using ajax
-function getTreeView() {
+function getTreeView(lang = "en") {
+ var url = "/ajax/classes/treeview?ontology="+jQuery(document).data().bp.ont_viewer.ontology_id+"&lang=" + lang + "&conceptid="+encodeURIComponent(jQuery(document).data().bp.ont_viewer.concept_id);
jQuery.ajax({
- url: "/ajax/classes/treeview?ontology="+jQuery(document).data().bp.ont_viewer.ontology_id+"&conceptid="+encodeURIComponent(jQuery(document).data().bp.ont_viewer.concept_id),
+ url: url,
success: function(data) {
placeTreeView(data);
},
error: function(data) {
- jQuery.get("/ajax/classes/treeview?ontology="+jQuery(document).data().bp.ont_viewer.ontology_id+"&conceptid=root", function(data){
+ var url = "/ajax/classes/treeview?ontology="+jQuery(document).data().bp.ont_viewer.ontology_id+"&lang=" + lang + "&conceptid=root";
+ jQuery.get(url, function(data) {
var rootTree = "Displaying the path to this class has taken too long. You can browse classes below.
" + data;
placeTreeView(rootTree);
});
@@ -201,6 +203,7 @@ function getTreeView() {
// We do this right after writing #sd_content to the dom to make sure it loads before other async portions of the page
jQuery(document).ready(function(){
if (pageUsesTreeView()) {
- getTreeView();
+ var lang = jQuery(document).data().bp.ont_viewer.lang;
+ getTreeView(lang);
}
});
diff --git a/app/assets/javascripts/bp_ontology_viewer.js.erb b/app/assets/javascripts/bp_ontology_viewer.js.erb
index e595cf3c23..276cfa27d5 100644
--- a/app/assets/javascripts/bp_ontology_viewer.js.erb
+++ b/app/assets/javascripts/bp_ontology_viewer.js.erb
@@ -82,18 +82,16 @@ function displayTree(data) {
var metadata_only = jQuery(document).data().bp.ont_viewer.metadata_only;
var purl_prefix = jQuery(document).data().bp.ont_viewer.purl_prefix;
var concept_name_title = jQuery(document).data().bp.ont_viewer.concept_name_title;
+ var lang = jQuery(document).data().bp.ont_viewer.lang;
// Check to see if we're actually loading a new concept or just displaying the one we already loaded previously
if (typeof new_concept_id === 'undefined' || new_concept_id == concept_id) {
-
if (concept_id !== "") {
History.replaceState({p:"classes", conceptid:concept_id}, jQuery.bioportal.ont_pages["classes"].page_name + " | " + org_site, "?p=classes" + "&conceptid=" + concept_id);
}
jQuery.unblockUI();
return;
-
} else {
-
var new_concept_param = (typeof new_concept_id === 'undefined') ? "" : "&conceptid=" + new_concept_id;
if (typeof new_concept_id !== 'undefined') {
@@ -137,7 +135,7 @@ function displayTree(data) {
simpleTreeCollection.get(0).setTreeNodes(list);
// Simulate node click
- nodeClicked(data.conceptid);
+ nodeClicked(data.conceptid, lang);
// Make "clicked" node active
jQuery("a.active").removeClass("active");
@@ -146,7 +144,7 @@ function displayTree(data) {
// Clear the search box
jQuery("#search_box").val("");
} else {
- nodeClicked(data.conceptid);
+ nodeClicked(data.conceptid, lang);
// Clear the search box
jQuery("#search_box").val("");
@@ -161,7 +159,7 @@ function displayTree(data) {
if (document.getElementById(new_concept_id) !== null) {
// We have a visible node that's been clicked, get the details for that node
jQuery.bioportal.ont_pages["classes"].published = true;
- nodeClicked(new_concept_id);
+ nodeClicked(new_concept_id, lang);
} else {
// Get a new copy of the tree because our concept isn't visible
// This could be due to using the forward/back button
@@ -201,6 +199,12 @@ function showOntologyContent(content_section) {
// Instead, fire some history events
var nav_ont = function(link) {
var page = jQuery(link).attr("data-bp-ont-page");
+
+ if (jQuery(document).data().bp.ont_viewer.lang_sections.includes(page)) {
+ jQuery("#navbar-ontology li.lang-dropdown").show();
+ } else {
+ jQuery("#navbar-ontology li.lang-dropdown").hide();
+ }
History.pushState({p:page}, jQuery.bioportal.ont_pages[page].page_name + " | " + jQuery(document).data().bp.ont_viewer.org_site, "?p=" + page);
}
diff --git a/app/assets/javascripts/bp_visualize.js.erb b/app/assets/javascripts/bp_visualize.js.erb
index 0e4b255426..4e5740ded7 100644
--- a/app/assets/javascripts/bp_visualize.js.erb
+++ b/app/assets/javascripts/bp_visualize.js.erb
@@ -98,7 +98,10 @@
jQuery(document).data().bp.classesTab.search_box_init = function(){
if (jQuery("#search_box").bioportal_autocomplete) {
jQuery("#search_box").bioportal_autocomplete("/search/json_search/"+jQuery(document).data().bp.ontology.acronym, {
- extraParams: { objecttypes: "class" },
+ extraParams: {
+ objecttypes: "class",
+ lang: jQuery(document).data().bp.ont_viewer.lang
+ },
selectFirst: true,
lineSeparator: "~!~",
matchSubset: 0,
diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss
index 6686c3dace..3647b07fa4 100644
--- a/app/assets/stylesheets/application.css.scss
+++ b/app/assets/stylesheets/application.css.scss
@@ -19,6 +19,7 @@
*= require thickbox
*= require select2
*= require trumbowyg
+ *= require flag-icon
*
*/
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 488cbda5a1..06cd2e3024 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -243,7 +243,8 @@ def redirect_new_api(class_view = false)
not_found unless acronym
if class_view
@ontology = LinkedData::Client::Models::Ontology.find_by_acronym(acronym).first
- concept = get_class(params).first.to_s
+ @submission = get_ontology_submission_ready(@ontology)
+ concept = get_class(params, @submission).first.to_s
redirect_to "/ontologies/#{acronym}?p=classes#{params_string_for_redirect(params, prefix: "&")}", :status => :moved_permanently
else
redirect_to "/ontologies/#{acronym}#{params_string_for_redirect(params)}", :status => :moved_permanently
@@ -349,10 +350,10 @@ def using_captcha?
ENV['USE_RECAPTCHA'].present? && ENV['USE_RECAPTCHA'] == 'true'
end
- def get_class(params)
+ def get_class(params, submission)
+ lang = helpers.request_lang(submission)
if @ontology.flat?
-
ignore_concept_param = params[:conceptid].nil? ||
params[:conceptid].empty? ||
params[:conceptid].eql?("root") ||
@@ -367,34 +368,37 @@ def get_class(params)
@concept.children = []
else
# Display only the requested class in the tree
- @concept = @ontology.explore.single_class({full: true}, params[:conceptid])
+ @concept = @ontology.explore.single_class({full: true, lang: lang}, params[:conceptid])
@concept.children = []
end
@root = LinkedData::Client::Models::Class.new
@root.children = [@concept]
-
else
-
# not ignoring 'bp_fake_root' here
ignore_concept_param = params[:conceptid].nil? ||
params[:conceptid].empty? ||
params[:conceptid].eql?("root")
+
if ignore_concept_param
# get the top level nodes for the root
# TODO_REV: Support views? Replace old view call: @ontology.top_level_classes(view)
- roots = @ontology.explore.roots
+ roots = @ontology.explore.roots(lang: lang)
+
if roots.nil? || roots.empty?
LOG.add :debug, "Missing roots for #{@ontology.acronym}"
not_found
end
@root = LinkedData::Client::Models::Class.new(read_only: true)
- @root.children = roots.sort{|x,y| (x.prefLabel || "").downcase <=> (y.prefLabel || "").downcase}
+ @root.children = roots.sort{|x,y|
+ x.prefLabel = helpers.link_last_part(x.id) if x.prefLabel.to_s.empty?
+ y.prefLabel = helpers.link_last_part(y.id) if y.prefLabel.to_s.empty?
+ (x.prefLabel || "").downcase <=> (y.prefLabel || "").downcase}
# get the initial concept to display
root_child = @root.children.first
+ @concept = root_child.explore.self(full: true, lang: lang)
- @concept = root_child.explore.self(full: true)
# Some ontologies have "too many children" at their root. These will not process and are handled here.
if @concept.nil?
LOG.add :debug, "Missing class #{root_child.links.self}"
@@ -402,20 +406,23 @@ def get_class(params)
end
else
# if the id is coming from a param, use that to get concept
- @concept = @ontology.explore.single_class({full: true}, params[:conceptid])
+ @concept = @ontology.explore.single_class({full: true, lang: lang}, params[:conceptid])
if @concept.nil? || @concept.errors
LOG.add :debug, "Missing class #{@ontology.acronym} / #{params[:conceptid]}"
not_found
end
# Create the tree
- rootNode = @concept.explore.tree(include: "prefLabel,hasChildren,obsolete")
+ rootNode = @concept.explore.tree(include: "prefLabel,hasChildren,obsolete", lang: lang)
+
if rootNode.nil? || rootNode.empty?
- roots = @ontology.explore.roots
+ roots = @ontology.explore.roots(lang: lang)
+
if roots.nil? || roots.empty?
LOG.add :debug, "Missing roots for #{@ontology.acronym}"
not_found
end
+
if roots.any? {|c| c.id == @concept.id}
rootNode = roots
else
@@ -423,10 +430,12 @@ def get_class(params)
end
end
@root = LinkedData::Client::Models::Class.new(read_only: true)
- @root.children = rootNode.sort{|x,y| (x.prefLabel || "").downcase <=> (y.prefLabel || "").downcase}
+ @root.children = rootNode.sort{|x,y|
+ x.prefLabel = helpers.link_last_part(x.id) if x.prefLabel.to_s.empty?
+ y.prefLabel = helpers.link_last_part(y.id) if y.prefLabel.to_s.empty?
+ (x.prefLabel || "").downcase <=> (y.prefLabel || "").downcase}
end
end
-
@concept
end
diff --git a/app/controllers/concepts_controller.rb b/app/controllers/concepts_controller.rb
index f518eed670..b945f04e60 100644
--- a/app/controllers/concepts_controller.rb
+++ b/app/controllers/concepts_controller.rb
@@ -16,13 +16,15 @@ def show
# find_by_acronym includes views by default
@ontology = LinkedData::Client::Models::Ontology.find_by_acronym(params[:ontology]).first
+ @submission = get_ontology_submission_ready(@ontology)
@ob_instructions = helpers.ontolobridge_instructions_template(@ontology)
if request.xhr?
display = params[:callback].eql?('load') ? { full: true } : { display: 'prefLabel' }
+ display[:language] = helpers.request_lang(@submission)
@concept = @ontology.explore.single_class(display, params[:id])
not_found if @concept.nil?
- show_ajax_request
+ show_ajax_request(@submission)
else
render plain: 'Non-AJAX requests are not accepted at this URL', status: :forbidden
end
@@ -53,7 +55,8 @@ def show_tree
if @ontology.nil?
not_found
else
- get_class(params)
+ @submission = get_ontology_submission_ready(@ontology)
+ get_class(params, @submission)
render partial: 'ontologies/treeview'
end
end
@@ -105,14 +108,18 @@ def redirect_new_api
# Load data for a concept or retrieve a concept's children, depending on the value of the :callback parameter.
# Children are retrieved for drawing ontology class trees.
- def show_ajax_request
+ def show_ajax_request(submission)
case params[:callback]
when 'load'
gather_details
render partial: 'load'
when 'children'
- @children = @concept.explore.children(pagesize: 750).collection || []
- @children.sort! { |x, y| (x.prefLabel || '').downcase <=> (y.prefLabel || '').downcase }
+ @children = @concept.explore.children(pagesize: 750, language: helpers.request_lang(submission)).collection || []
+ @children.sort! do |x, y|
+ x.prefLabel = helpers.link_last_part(x.id) if x.prefLabel.to_s.empty?
+ y.prefLabel = helpers.link_last_part(y.id) if y.prefLabel.to_s.empty?
+ (x.prefLabel || '').downcase <=> (y.prefLabel || '').downcase
+ end
render partial: 'child_nodes'
end
end
@@ -123,4 +130,5 @@ def gather_details
@delete_mapping_permission = check_delete_mapping_permission(@mappings)
update_tab(@ontology, @concept.id)
end
+
end
diff --git a/app/controllers/language_controller.rb b/app/controllers/language_controller.rb
new file mode 100644
index 0000000000..0ccf6b59c5
--- /dev/null
+++ b/app/controllers/language_controller.rb
@@ -0,0 +1,21 @@
+class LanguageController < ApplicationController
+
+ # set locale to the language selected by the user
+ def set_locale_language
+ language = params[:language].strip.downcase.to_sym
+ supported_languages = I18n.available_locales
+
+ if language
+ if supported_languages.include?(language)
+ cookies.permanent[:locale] = language
+ else
+ # in case we want to show a message if the language is not available
+ flash.now[:notice] = t('language.translation_not_available', language: language)
+ logger.error flash.now[:notice]
+ end
+ end
+
+ redirect_to request.referer || root_path
+ end
+
+end
diff --git a/app/controllers/ontologies_controller.rb b/app/controllers/ontologies_controller.rb
index 4c0847c5f1..aa8fadeed4 100644
--- a/app/controllers/ontologies_controller.rb
+++ b/app/controllers/ontologies_controller.rb
@@ -132,14 +132,14 @@ def index
end
def classes
- get_class(params)
+ @submission = get_ontology_submission_ready(@ontology)
+ get_class(params, @submission)
if ["application/ld+json", "application/json"].include?(request.accept)
render plain: @concept.to_jsonld, content_type: request.accept and return
end
@current_purl = @concept.purl if Rails.configuration.settings.purl[:enabled]
- @submission = get_ontology_submission_ready(@ontology)
unless @concept.id == "bp_fake_root"
@notes = @concept.explore.notes
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 95d08d8ff7..d8d9d028b1 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -61,18 +61,19 @@ def remove_owl_notation(string)
end
end
- def draw_tree(root, id = nil, type = "Menu")
+ def draw_tree(root, id = nil, type = "Menu", submission)
if id.nil?
id = root.children.first.id
end
# TODO: handle tree view for obsolete classes, e.g. 'http://purl.obolibrary.org/obo/GO_0030400'
- raw build_tree(root, "", id) # returns a string, representing nested list items
+ raw build_tree(root, "", id, submission) # returns a string, representing nested list items
end
- def build_tree(node, string, id)
+ def build_tree(node, string, id, submission)
if node.children.nil? || node.children.length < 1
return string # unchanged
end
+
node.children.sort! {|a,b| (a.prefLabel || a.id).downcase <=> (b.prefLabel || b.id).downcase}
for child in node.children
if child.id.eql?(id)
@@ -93,12 +94,13 @@ def build_tree(node, string, id)
string << "#{child.prefLabel}"
else
icons = child.relation_icon(node)
- string << " #{child.prefLabel({use_html: true})} #{icons}"
+ string << " #{child.prefLabel({use_html: true})} #{icons}"
+
if child.hasChildren && !child.expanded?
- string << ""
+ string << ""
elsif child.expanded?
string << ""
- build_tree(child, string, id)
+ build_tree(child, string, id, submission)
string << "
"
end
string << ""
@@ -234,6 +236,16 @@ def at_slice?
!@subdomain_filter.nil? && !@subdomain_filter[:active].nil? && @subdomain_filter[:active] == true
end
+ def link_last_part(url)
+ return "" if url.nil?
+
+ if url.include?('#')
+ url.split('#').last
+ else
+ url.split('/').last
+ end
+ end
+
def truncate_with_more(text, options = {})
length ||= options[:length] ||= 30
trailing_text ||= options[:trailing_text] ||= " ... "
@@ -362,5 +374,4 @@ def get_link_for_ont_ajax(ont_acronym)
end
###END ruby equivalent of JS code in bp_ajax_controller.
-
end
diff --git a/app/helpers/internationalisation_helper.rb b/app/helpers/internationalisation_helper.rb
new file mode 100644
index 0000000000..6bda49f76d
--- /dev/null
+++ b/app/helpers/internationalisation_helper.rb
@@ -0,0 +1,43 @@
+module InternationalisationHelper
+
+ # Implement logic to make the term 'ontology' configurable throughout the portal,
+ # allowing it to be replaced with the variable $RESOURCE_TERM
+ def self.t(*args, **kwargs)
+ return I18n.t(*args, **kwargs) unless $RESOURCE_TERM
+
+ begin
+ original_translation = I18n.t(*args, **kwargs)
+ downcase_translation = original_translation.downcase
+ rescue StandardError => e
+ return e.message
+ end
+
+ term = I18n.t("resource_term.ontology")
+ plural_term = I18n.t("resource_term.ontology_plural")
+ single_term = I18n.t("resource_term.ontology_single")
+ resource = I18n.t("resource_term.#{$RESOURCE_TERM}")
+ resources = I18n.t("resource_term.#{$RESOURCE_TERM}_plural")
+ a_resource = I18n.t("resource_term.#{$RESOURCE_TERM}_single")
+
+ if downcase_translation.include?(term) && resource
+ replacement = resource.capitalize
+ replacement = resource if downcase_translation.include?(term)
+ if downcase_translation.include?(single_term)
+ term = single_term
+ replacement = a_resource
+ end
+ original_translation.gsub(term, replacement)
+ elsif downcase_translation.include?(plural_term) && resources
+ replacement = resources.capitalize
+ replacement = resources if downcase_translation.include?(plural_term)
+ original_translation.gsub(plural_term, replacement)
+ else
+ I18n.t(*args, **kwargs)
+ end
+ end
+
+ # def t(*args, **kwargs)
+ # InternationalisationHelper.t(*args, **kwargs)
+ # end
+
+end
diff --git a/app/helpers/multi_languages_helper.rb b/app/helpers/multi_languages_helper.rb
new file mode 100644
index 0000000000..d12d5dd881
--- /dev/null
+++ b/app/helpers/multi_languages_helper.rb
@@ -0,0 +1,146 @@
+module MultiLanguagesHelper
+
+ def portal_language_help_text
+ t('language.portal_language_help_text')
+ end
+
+ def portal_languages
+ {
+ en: { badge: nil, disabled: false },
+ fr: { badge: 'beta', disabled: false },
+ it: { badge: 'coming', disabled: true },
+ de: { badge: 'coming', disabled: true }
+ }
+ end
+
+ def portal_language_selector
+ languages = portal_languages
+ selected_language = portal_lang
+ selected_language = content_tag(:span, selected_language.upcase, data: { controller: 'tooltip' }, title: portal_language_help_text)
+ render DropdownButtonComponent.new do |d|
+ d.header { selected_language }
+ d.section(divide: false, selected_index: languages.find_index(selected_language)) do |s|
+ languages.each do |lang, metadata|
+ s.item do
+ text = content_tag(:div, class: 'd-flex align-items-center') do
+ content_tag(:span, render(LanguageFieldComponent.new(value: lang, auto_label: true)), class: 'mr-1') + beta_badge(metadata[:badge])
+ end
+ link_options = { data: { turbo: false } }
+
+ if metadata[:disabled]
+ link_options[:class] = 'disabled-link'
+ link_options[:disabled] = 'disabled'
+ end
+
+ link_to(text, "/locale/#{lang}", link_options)
+ end
+ end
+
+ end
+ end
+ end
+
+ def search_language_help_text
+ content_tag(:div, style: 'width: 300px; text-align: center') do
+ t('language.search_language_help_text')
+ end
+ end
+
+ def search_languages
+ # top ten spoken languages
+ portal_languages.keys + %w[zh es hi ar bn pt ru ur id]
+ end
+
+ def language_hash(concept_label, multiple: false)
+ if concept_label.is_a?(Array)
+ return concept_label.first unless multiple
+ return concept_label
+ end
+
+ return concept_label.to_h.reject { |key, _| %i[links context].include?(key) } if concept_label.is_a?(OpenStruct)
+
+ concept_label
+ end
+
+ def sorted_labels(labels)
+ Array(labels).sort_by { |label| label['prefLabel'].is_a?(String) ? label['prefLabel'] : label['prefLabel'].last }
+ end
+
+ def select_language_label(concept_label, platform_languages = %i[en fr])
+ concept_value = nil
+
+ concept = language_hash(concept_label)
+
+ return ['@none', concept] if concept.is_a?(String)
+
+ concept = concept.to_h
+
+ platform_languages.each do |lang|
+ if concept[lang]
+ concept_value = [lang, concept[lang]]
+ break
+ end
+ end
+
+ concept_value || concept.to_a.first
+ end
+
+ def main_language_label(label)
+ select_language_label(label)&.last
+ end
+
+ def selected_language_label(label)
+ language_hash(label).values.first
+ end
+
+ def content_language_selector(id: 'content_language', name: 'content_language')
+ languages, selected = content_languages
+ select_tag(name, options_for_select(languages, selected || 'all'), class: "form-select",
+ data: { controller: "language-change", 'language-change-section-value': "classes", action: "change->language-change#dispatchLangChangeEvent" }) if languages&.length > 1
+ end
+
+ def content_languages(submission = @submission || @submission_latest)
+ current_lang = request_lang(submission).downcase
+ submission_lang = submission_languages(submission)
+ # Transform each language into a select option
+ submission_lang = submission_lang.map do |lang|
+ lang = lang.split('/').last.upcase
+ lang = ISO_639.find(lang.to_s.downcase)
+ next nil unless lang
+ [lang.english_name, lang.alpha2]
+ end.compact
+
+ [submission_lang, current_lang]
+ end
+
+ def portal_lang
+ session[:locale] || 'en'
+ end
+
+ def request_lang(submission = @submission || @submission_latest)
+ lang = params[:language] || params[:lang]
+ lang = submission_languages(submission)&.first unless lang
+ lang = portal_lang unless lang
+ lang
+ end
+
+ def lang_code(code_in)
+ code_out = code_in
+ case code_in
+ when 'en'
+ code_out = 'us'
+ when 'ar'
+ code_out = 'sa'
+ when 'hi'
+ code_out = 'in'
+ when 'ur'
+ code_out = 'pk'
+ when 'zh'
+ code_out = 'cn'
+ when 'ja'
+ code_out = 'jp'
+ end
+ code_out
+ end
+
+end
diff --git a/app/helpers/ontologies_helper.rb b/app/helpers/ontologies_helper.rb
index 88ea877d94..e255fdedd4 100644
--- a/app/helpers/ontologies_helper.rb
+++ b/app/helpers/ontologies_helper.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
+require 'iso-639'
module OntologiesHelper
+
+ LANGUAGE_FILTERABLE_SECTIONS = %w[classes properties].freeze
+
def additional_details
return '' if $ADDITIONAL_ONTOLOGY_DETAILS.nil? || $ADDITIONAL_ONTOLOGY_DETAILS[@ontology.acronym].nil?
@@ -158,4 +162,34 @@ def change_requests_enabled?(ontology_acronym)
Rails.configuration.change_request[:ontologies].include? ontology_acronym.to_sym
end
+
+ def current_section
+ (params[:p]) ? params[:p] : 'summary'
+ end
+
+ def ontology_data_sections
+ LANGUAGE_FILTERABLE_SECTIONS
+ end
+
+ def ontology_data_section?(section_title = current_section)
+ ontology_data_sections.include?(section_title)
+ end
+
+ def language_selector_tag(name)
+ content_language_selector(id: name, name: name)
+ end
+
+ def submission_languages(submission = @submission)
+ Array(submission&.naturalLanguage).map { |natural_language| natural_language.split('/').last }.compact
+ end
+
+ def abbreviations_to_languages(abbreviations)
+ # Use iso-639 gem to convert language codes to their English names
+ languages = abbreviations.map do |abbr|
+ language = ISO_639.find_by_code(abbr) || ISO_639.find_by_english_name(abbr)
+ language ? language.english_name : abbr
+ end
+ languages.sort
+ end
+
end
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
index c4d0fd2b2e..273754277c 100644
--- a/app/javascript/controllers/index.js
+++ b/app/javascript/controllers/index.js
@@ -4,5 +4,9 @@
import { application } from "./application"
+import LanguageChangeController from "./language_change_controller"
+application.register("language-change", LanguageChangeController)
+
import ClipboardController from "./clipboard_controller"
application.register("clipboard", ClipboardController)
+
diff --git a/app/javascript/controllers/language_change_controller.js b/app/javascript/controllers/language_change_controller.js
new file mode 100644
index 0000000000..b1fc34aa5f
--- /dev/null
+++ b/app/javascript/controllers/language_change_controller.js
@@ -0,0 +1,47 @@
+import { Controller } from "@hotwired/stimulus"
+
+// Connects to data-controller="language-change"
+export default class extends Controller {
+
+
+ connect() {
+ // can be used for debugging
+ // console.log(this.element.value);
+ jQuery(document).data().bp.ont_viewer.lang = this.element.value;
+ }
+
+ dispatchLangChangeEvent() {
+ jQuery(document).data().bp.ont_viewer.lang = this.element.value;
+
+ var url = window.location.href;
+ url = this.removeURLParameter(url, 'lang');
+ if (url.indexOf('?') > -1) {
+ url += '&lang=' + this.element.value;
+ } else {
+ url += '?lang=' + this.element.value;
+ }
+ jQuery.blockUI({ message: 'Switching language...
', showOverlay: true });
+ window.location.href = url;
+ }
+
+ removeURLParameter(url, parameter) {
+ //prefer to use l.search if you have a location/link object
+ var urlparts = url.split('?');
+
+ if (urlparts.length >= 2) {
+ var prefix = encodeURIComponent(parameter) + '=';
+ var pars = urlparts[1].split(/[&;]/g);
+
+ //reverse iteration as may be destructive
+ for (var i = pars.length; i-- > 0;) {
+ //idiom for string.startsWith
+ if (pars[i].lastIndexOf(prefix, 0) !== -1) {
+ pars.splice(i, 1);
+ }
+ }
+ return urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : '');
+ }
+ return url;
+ }
+
+}
diff --git a/app/views/concepts/_child_nodes.html.haml b/app/views/concepts/_child_nodes.html.haml
index 79107a3cb3..b734cc5944 100644
--- a/app/views/concepts/_child_nodes.html.haml
+++ b/app/views/concepts/_child_nodes.html.haml
@@ -1,8 +1,9 @@
- output =""
- for child in @children
- icons = child.relation_icon(@concept)
- - output << " #{child.prefLabel} #{icons}"
+ - output << " #{child.prefLabel} #{icons}"
+
- if child.hasChildren
- - output << ""
+ - output << ""
- output << ""
= raw output
diff --git a/app/views/concepts/_details.html.haml b/app/views/concepts/_details.html.haml
index 4bc9657688..cb0ff44494 100644
--- a/app/views/concepts/_details.html.haml
+++ b/app/views/concepts/_details.html.haml
@@ -25,7 +25,11 @@
%tr
%td Preferred Name
%td
- %p= @concept.prefLabel({:use_html => true}).html_safe
+ %p
+ - if @concept.prefLabel({:use_html => false}).to_s.empty?
+ %div.alert.alert-warning= 'No preferred name provided for selected language'
+ - else
+ = @concept.prefLabel({:use_html => true}).html_safe
%td
%tr
%td Synonyms
diff --git a/app/views/concepts/_request_term.html.haml b/app/views/concepts/_request_term.html.haml
index 7185c38a35..7c3bed4a93 100644
--- a/app/views/concepts/_request_term.html.haml
+++ b/app/views/concepts/_request_term.html.haml
@@ -36,11 +36,7 @@
var g_prefLabel;
jQuery(document).ready(function() {
- g_prefLabel = '#{@concept.prefLabel({:use_html => false}).html_safe}';
-
- if (!g_prefLabel) {
- g_prefLabel = '#{@concept.id}';
- }
+ g_prefLabel = '#{@concept.prefLabel({:use_html => false}).to_s.empty? ? @concept.id : @concept.prefLabel({:use_html => false}).html_safe}';
var isPopulated = window.localStorage.getItem('request_term_form_populated');
if (isPopulated) {
diff --git a/app/views/layouts/_ontology_viewer.html.haml b/app/views/layouts/_ontology_viewer.html.haml
index 64f4899d0c..0370abc0a0 100644
--- a/app/views/layouts/_ontology_viewer.html.haml
+++ b/app/views/layouts/_ontology_viewer.html.haml
@@ -36,6 +36,8 @@
jQuery(document).data().bp.ont_viewer.purl_prefix = "#{(Rails.configuration.settings.purl[:enabled] ? Rails.configuration.settings.purl[:prefix]+"/"+@ontology.acronym : '')}";
jQuery(document).data().bp.ont_viewer.concept_name_title = (jQuery(document).data().bp.ont_viewer.concept_name == "") ?
"" : " - " + jQuery(document).data().bp.ont_viewer.concept_name;
+ jQuery(document).data().bp.ont_viewer.lang = "#{request_lang(sub)}";
+ jQuery(document).data().bp.ont_viewer.lang_sections = #{ontology_data_sections.to_json.html_safe};
-# Modal dialog for creating a new mapping (must reside in a top-level position in the document to display properly).
%div#createNewMappingModal{class: "modal fade", tabindex: "-1", "aria-labelledby": "createNewMappingLabel"}
@@ -139,6 +141,8 @@
class: "nav-link", type: 'button', role: "tab",
data: {bp_ont_page: "widgets", "bs-toggle": "tab", "bs-target": "#ont_widgets_content"},
aria: {controls: "ont_widgets_content", selected: "false"})
+ %li{style: "display: #{ontology_data_section? ? 'block' : 'none'}", class: 'nav-item lang-dropdown', role: 'presentation'}
+ = language_selector_tag(:content_language)
%div.card-body
-# Tab panes for displaying ontology content sections
%div.tab-content{id: "ontology_content"}
@@ -160,7 +164,6 @@
%div.tab-pane{id: "ont_widgets_content", role: "tabpanel", aria: {labelledby: "ont-widgets-tab"}}
- if content_section.eql?("widgets")
= yield
-
- if Rails.env.appliance?
= render partial: "footer_appliance"
diff --git a/app/views/ontologies/_metadata.html.haml b/app/views/ontologies/_metadata.html.haml
index aa5c44a6dc..df5be9e159 100644
--- a/app/views/ontologies/_metadata.html.haml
+++ b/app/views/ontologies/_metadata.html.haml
@@ -49,6 +49,9 @@
%tr
%td Groups
%td= groups.map {|g| groups_hash[g].name}.sort.join(", ")
+ %tr
+ %td Language
+ %td= abbreviations_to_languages(@submission_latest.naturalLanguage).join(", ")
= raw additional_details
-# Submissions pane
diff --git a/app/views/ontologies/_treeview.html.haml b/app/views/ontologies/_treeview.html.haml
index 3640b54510..20db396a8b 100644
--- a/app/views/ontologies/_treeview.html.haml
+++ b/app/views/ontologies/_treeview.html.haml
@@ -2,4 +2,4 @@
%ul.simpleTree
%li.root
%ul
- = draw_tree(@root, @concept.id) # application_helper::draw_tree
+ = draw_tree(@root, @concept.id, @submission) # application_helper::draw_tree
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 8562532e75..e3187b171e 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,5 +1,4 @@
en:
-
activerecord:
errors:
models:
@@ -48,7 +47,7 @@ en:
find_ontology_placeholder: Start typing ontology name, then choose from list
query_placeholder: Enter a class, e.g. Melanoma
tagline: the world's most comprehensive repository of biomedical ontologies
- title: Welcome to the %{organization}
+ title: Welcome to the %{organization}
welcome: Welcome to %{site},
help:
welcome: Welcome to the National Center for Biomedical Ontology’s %{site}. %{site} is a web-based application for accessing and sharing biomedical ontologies.
diff --git a/db/schema.rb b/db/schema.rb
index fbc53cdaba..5d5db5ddc7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -28,20 +28,6 @@
t.datetime "updated_at", precision: nil, null: false
end
- create_table "margin_notes", id: :integer, charset: "utf8", force: :cascade do |t|
- t.integer "parent_id"
- t.integer "mapping_id"
- t.integer "note_type"
- t.integer "user_id"
- t.integer "ontology_id"
- t.integer "ontology_version_id"
- t.string "concept_id"
- t.string "subject"
- t.text "comment"
- t.datetime "created_at", precision: nil
- t.datetime "updated_at", precision: nil
- end
-
create_table "ontologies", charset: "utf8", force: :cascade do |t|
t.string "acronym", null: false
t.text "new_term_instructions"
diff --git a/yarn.lock b/yarn.lock
index 6da874dbfd..7da15e91d9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,120 +2,120 @@
# yarn lockfile v1
-"@esbuild/aix-ppc64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz#509621cca4e67caf0d18561a0c56f8b70237472f"
- integrity sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==
-
-"@esbuild/android-arm64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz#109a6fdc4a2783fc26193d2687827045d8fef5ab"
- integrity sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==
-
-"@esbuild/android-arm@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.0.tgz#1397a2c54c476c4799f9b9073550ede496c94ba5"
- integrity sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==
-
-"@esbuild/android-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.0.tgz#2b615abefb50dc0a70ac313971102f4ce2fdb3ca"
- integrity sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==
-
-"@esbuild/darwin-arm64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz#5c122ed799eb0c35b9d571097f77254964c276a2"
- integrity sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==
-
-"@esbuild/darwin-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz#9561d277002ba8caf1524f209de2b22e93d170c1"
- integrity sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==
-
-"@esbuild/freebsd-arm64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz#84178986a3138e8500d17cc380044868176dd821"
- integrity sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==
-
-"@esbuild/freebsd-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz#3f9ce53344af2f08d178551cd475629147324a83"
- integrity sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==
-
-"@esbuild/linux-arm64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz#24efa685515689df4ecbc13031fa0a9dda910a11"
- integrity sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==
-
-"@esbuild/linux-arm@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz#6b586a488e02e9b073a75a957f2952b3b6e87b4c"
- integrity sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==
-
-"@esbuild/linux-ia32@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz#84ce7864f762708dcebc1b123898a397dea13624"
- integrity sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==
-
-"@esbuild/linux-loong64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz#1922f571f4cae1958e3ad29439c563f7d4fd9037"
- integrity sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==
-
-"@esbuild/linux-mips64el@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz#7ca1bd9df3f874d18dbf46af009aebdb881188fe"
- integrity sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==
-
-"@esbuild/linux-ppc64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz#8f95baf05f9486343bceeb683703875d698708a4"
- integrity sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==
-
-"@esbuild/linux-riscv64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz#ca63b921d5fe315e28610deb0c195e79b1a262ca"
- integrity sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==
-
-"@esbuild/linux-s390x@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz#cb3d069f47dc202f785c997175f2307531371ef8"
- integrity sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==
-
-"@esbuild/linux-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz#ac617e0dc14e9758d3d7efd70288c14122557dc7"
- integrity sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==
-
-"@esbuild/netbsd-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz#6cc778567f1513da6e08060e0aeb41f82eb0f53c"
- integrity sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==
-
-"@esbuild/openbsd-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz#76848bcf76b4372574fb4d06cd0ed1fb29ec0fbe"
- integrity sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==
-
-"@esbuild/sunos-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz#ea4cd0639bf294ad51bc08ffbb2dac297e9b4706"
- integrity sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==
-
-"@esbuild/win32-arm64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz#a5c171e4a7f7e4e8be0e9947a65812c1535a7cf0"
- integrity sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==
-
-"@esbuild/win32-ia32@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz#f8ac5650c412d33ea62d7551e0caf82da52b7f85"
- integrity sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==
-
-"@esbuild/win32-x64@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz#2efddf82828aac85e64cef62482af61c29561bee"
- integrity sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==
+"@esbuild/aix-ppc64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537"
+ integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==
+
+"@esbuild/android-arm64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9"
+ integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==
+
+"@esbuild/android-arm@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995"
+ integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==
+
+"@esbuild/android-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98"
+ integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==
+
+"@esbuild/darwin-arm64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb"
+ integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==
+
+"@esbuild/darwin-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0"
+ integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==
+
+"@esbuild/freebsd-arm64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911"
+ integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==
+
+"@esbuild/freebsd-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c"
+ integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==
+
+"@esbuild/linux-arm64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5"
+ integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==
+
+"@esbuild/linux-arm@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c"
+ integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==
+
+"@esbuild/linux-ia32@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa"
+ integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==
+
+"@esbuild/linux-loong64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5"
+ integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==
+
+"@esbuild/linux-mips64el@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa"
+ integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==
+
+"@esbuild/linux-ppc64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20"
+ integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==
+
+"@esbuild/linux-riscv64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300"
+ integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==
+
+"@esbuild/linux-s390x@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685"
+ integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==
+
+"@esbuild/linux-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff"
+ integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==
+
+"@esbuild/netbsd-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6"
+ integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==
+
+"@esbuild/openbsd-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf"
+ integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==
+
+"@esbuild/sunos-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f"
+ integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==
+
+"@esbuild/win32-arm64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90"
+ integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==
+
+"@esbuild/win32-ia32@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23"
+ integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==
+
+"@esbuild/win32-x64@0.20.2":
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
+ integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
"@hotwired/stimulus@^3.2.2":
version "3.2.2"
@@ -123,17 +123,17 @@
integrity sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==
"@hotwired/turbo-rails@^8.0.3":
- version "8.0.3"
- resolved "https://registry.yarnpkg.com/@hotwired/turbo-rails/-/turbo-rails-8.0.3.tgz#e60375f4eea4b30ec0cd6d7e3fdb3d6349a2b57b"
- integrity sha512-n5B9HdFsNiGJfXFAriCArmvFZyznIh/OriB5ZVAWz4Fsi4oLkpgmJNw5pibBAM7NMQQGN6cfKa/nhZT4LWcqbQ==
+ version "8.0.4"
+ resolved "https://registry.yarnpkg.com/@hotwired/turbo-rails/-/turbo-rails-8.0.4.tgz#d224f524a9e33fe687cec5d706054eb6fe13fa5b"
+ integrity sha512-GHCv5+B2VzYZZvMFpg/g9JLx/8pl/8chcubSB7T+Xn1zYOMqAKB6cT80vvWUzxdwfm/2KfaRysfDz+BmvtjFaw==
dependencies:
- "@hotwired/turbo" "^8.0.3"
+ "@hotwired/turbo" "^8.0.4"
"@rails/actioncable" "^7.0"
-"@hotwired/turbo@^8.0.3":
- version "8.0.3"
- resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-8.0.3.tgz#338e07278f4b3c76921328d3c92dbc4831c209d0"
- integrity sha512-qLgp7d6JaegKjMToTJahosrFxV3odfSbiekispQ3soOzE5jnU+iEMWlRvYRe/jvy5Q+JWoywtf9j3RD4ikVjIg==
+"@hotwired/turbo@^8.0.4":
+ version "8.0.4"
+ resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-8.0.4.tgz#5c5361c06a37cdf10dcba4223f1afd0ca1c75091"
+ integrity sha512-mlZEFUZrJnpfj+g/XeCWWuokvQyN68WvM78JM+0jfSFc98wegm259vCbC1zSllcspRwbgXK31ibehCy5PA78/Q==
"@rails/actioncable@^7.0":
version "7.1.3"
@@ -141,30 +141,30 @@
integrity sha512-ojNvnoZtPN0pYvVFtlO7dyEN9Oml1B6IDM+whGKVak69MMYW99lC2NOWXWeE3bmwEydbP/nn6ERcpfjHVjYQjA==
esbuild@^0.20.0:
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.0.tgz#a7170b63447286cd2ff1f01579f09970e6965da4"
- integrity sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1"
+ integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==
optionalDependencies:
- "@esbuild/aix-ppc64" "0.20.0"
- "@esbuild/android-arm" "0.20.0"
- "@esbuild/android-arm64" "0.20.0"
- "@esbuild/android-x64" "0.20.0"
- "@esbuild/darwin-arm64" "0.20.0"
- "@esbuild/darwin-x64" "0.20.0"
- "@esbuild/freebsd-arm64" "0.20.0"
- "@esbuild/freebsd-x64" "0.20.0"
- "@esbuild/linux-arm" "0.20.0"
- "@esbuild/linux-arm64" "0.20.0"
- "@esbuild/linux-ia32" "0.20.0"
- "@esbuild/linux-loong64" "0.20.0"
- "@esbuild/linux-mips64el" "0.20.0"
- "@esbuild/linux-ppc64" "0.20.0"
- "@esbuild/linux-riscv64" "0.20.0"
- "@esbuild/linux-s390x" "0.20.0"
- "@esbuild/linux-x64" "0.20.0"
- "@esbuild/netbsd-x64" "0.20.0"
- "@esbuild/openbsd-x64" "0.20.0"
- "@esbuild/sunos-x64" "0.20.0"
- "@esbuild/win32-arm64" "0.20.0"
- "@esbuild/win32-ia32" "0.20.0"
- "@esbuild/win32-x64" "0.20.0"
+ "@esbuild/aix-ppc64" "0.20.2"
+ "@esbuild/android-arm" "0.20.2"
+ "@esbuild/android-arm64" "0.20.2"
+ "@esbuild/android-x64" "0.20.2"
+ "@esbuild/darwin-arm64" "0.20.2"
+ "@esbuild/darwin-x64" "0.20.2"
+ "@esbuild/freebsd-arm64" "0.20.2"
+ "@esbuild/freebsd-x64" "0.20.2"
+ "@esbuild/linux-arm" "0.20.2"
+ "@esbuild/linux-arm64" "0.20.2"
+ "@esbuild/linux-ia32" "0.20.2"
+ "@esbuild/linux-loong64" "0.20.2"
+ "@esbuild/linux-mips64el" "0.20.2"
+ "@esbuild/linux-ppc64" "0.20.2"
+ "@esbuild/linux-riscv64" "0.20.2"
+ "@esbuild/linux-s390x" "0.20.2"
+ "@esbuild/linux-x64" "0.20.2"
+ "@esbuild/netbsd-x64" "0.20.2"
+ "@esbuild/openbsd-x64" "0.20.2"
+ "@esbuild/sunos-x64" "0.20.2"
+ "@esbuild/win32-arm64" "0.20.2"
+ "@esbuild/win32-ia32" "0.20.2"
+ "@esbuild/win32-x64" "0.20.2"