Commit f2a7d145 authored by PiTrem's avatar PiTrem
Browse files

write owl as json in public after import

owl tree serialized from json file
with direct concat recent values from current_user profile
(no ols_term db queries)

keep public ontologies directory

fix import: RXNO 596 has array label

owl tree select: insensitive search

resolve #742
parent 7078eaec
......@@ -62,6 +62,9 @@
!/public/images/wild_card/
!/public/images/ghs/
/public/ontologies/*
!/public/ontologies/.keep
/uploads/*
!/public/attachments/.keep
......
......@@ -165,21 +165,22 @@ module Chemotion
optional :disableIds, type: Array, desc: 'disable term_ids'
end
post do
if params[:enableIds].present? && params[:enableIds].length > 0
params[:enableIds].each do |idkey|
term_id = idkey.split('|').first
ols = OlsTerm.find_by(owl_name: params[:owl_name], term_id: term_id)
ols.update!(is_enabled: true)
end
end
if params[:disableIds].present? && params[:disableIds].length > 0
params[:disableIds].each do |idkey|
term_id = idkey.split('|').first
ols = OlsTerm.find_by(owl_name: params[:owl_name], term_id: term_id)
ols.update!(is_enabled: false)
end
[:enableIds, :disableIds].each do |cat|
next unless params[cat].present?
term_ids = params[cat].map{|t| t.split('|').first.strip }
ids = OlsTerm.where(term_id: term_ids).pluck(:id)
OlsTerm.switch_by_ids(ids, cat == :enableIds)
end
true
# rewrite edited json file
result = Entities::OlsTermEntity.represent(
OlsTerm.where(owl_name: owl_name, is_enabled: true).arrange_serializable(:order => :label),
serializable: true
).unshift(
{'key': params[:name], 'title': '-- Recently selected --', selectable: false, 'children': []}
)
OlsTerm.write_public_file("#{owl_name}.edited", { ols_terms: result })
status 204
end
end
......@@ -199,6 +200,24 @@ module Chemotion
# discrete settings
nmr_13c = OlsTerm.find_by(owl_name: 'chmo', term_id: 'CHMO:0000595')
nmr_13c.update!(synonym: '13C NMR') if nmr_13c
# write original owl
result = Entities::OlsTermEntity.represent(
OlsTerm.where(owl_name: owl_name).arrange_serializable(:order => :label),
serializable: true
)
OlsTerm.write_public_file(owl_name, { ols_terms: result })
# write edited owl
result = Entities::OlsTermEntity.represent(
OlsTerm.where(owl_name: owl_name, is_enabled: true).arrange_serializable(:order => :label),
serializable: true
).unshift(
{'key': params[:name], 'title': '-- Recently selected --', selectable: false, 'children': []}
)
OlsTerm.write_public_file("#{owl_name}.edited", { ols_terms: result })
status 204
end
end
end
......
......@@ -8,33 +8,18 @@ module Chemotion
desc 'Get List'
params do
requires :name, type: String, desc: "OLS Name", values: %w[chmo rxno]
optional :is_enabled, type: Boolean, default: true, desc: 'Only list is_enabled ols terms'
optional :edited, type: Boolean, default: true, desc: 'Only list visible terms'
end
get 'list' do
unless params[:is_enabled]
list = OlsTerm.where(owl_name: params[:name]).arrange_serializable(:order => :label)
return { ols_terms: present(list, with: Entities::OlsTermEntity) }
end
list = OlsTerm.where(owl_name: params[:name], is_enabled: true)
.arrange_serializable(:order => :label)
result = present(list, with: Entities::OlsTermEntity)
file = Rails.public_path.join(
'ontologies',
"#{params[:name]}#{params[:edited] ? '.edited.json' : '.json'}"
)
result = JSON.parse(File.read(file, encoding: 'bom|utf-8')) if File.exist?(file)
recent_term_ids = current_user.profile&.data&.fetch(params[:name], nil)
if recent_term_ids.present?
ols = OlsTerm.where(owl_name: params[:name], term_id: recent_term_ids)
.select(<<~SQL
owl_name, ' ' || term_id as term_id, ancestry, label, synonym, synonyms
-- owl_name, term_id, ancestry, label || ' ' as label, synonym, synonyms
SQL
).order("label").as_json
if ols.present?
entities = Entities::OlsTermEntity.represent(ols, serializable: true)
result.unshift({'key': params[:name], 'title': '-- Recently selected --', selectable: false, 'children': entities})
end
end
{ ols_terms: result }
result['ols_terms'][0]['children'] = recent_term_ids if recent_term_ids.present?
result
end
get 'root' do
......
......@@ -135,7 +135,7 @@ module Chemotion
kinds = wellplate.container&.analyses&.pluck("extended_metadata->'kind'")
recent_ols_term_update('chmo', kinds) if kinds&.length&.positive?
{wellplate: ElementPermissionProxy.new(current_user, wellplate, user_ids).serialized}
{ wellplate: ElementPermissionProxy.new(current_user, wellplate, user_ids).serialized }
end
end
......
......@@ -15,9 +15,11 @@ module Entities
obj['label'] + ' (' + obj['synonym'] + ')'
end
end
expose :synonym do |obj|
obj['synonym']
end
expose :value do |obj|
if obj['owl_name'] == 'rxno' || obj['synonyms'].nil?
obj['term_id'] + ' | ' + obj['label']
......
module ProfileHelpers
extend Grape::API::Helpers
def recent_ols_term_update(name, ols_values, max=10)
return if ols_values.nil?
return if ols_values&.length == 0
return unless %w[chmo rxno].include?(name)
ols_values.each do |ols_value|
next if ols_value.nil?
term_id = ols_value.split('|').first.strip
next if term_id.nil? || term_id.length == 0
ols_value =~ /(\w+\:?\d+) \| ([^()]*) (\((.*)\))?/
term = {
'owl_name' => name,
'term_id' => $1,
'title' => $2,
'synonym' => $4,
'synonyms' => [$4],
'search' => ols_value,
'value' => ols_value
}
next unless term['term_id']
profile = current_user.profile
data = profile.data || {}
list = data[name]
if list.nil?
data.merge!(rxno: [term_id]) if name == 'rxno'
data.merge!(chmo: [term_id]) if name == 'chmo'
if list.present?
return if (list.find{ |t| t['term_id'] == term['term_id'] })
list.unshift(term)
data[name.to_sym] = list.first(max)
else
return if (list.include?(term_id))
list.unshift(term_id).uniq
data.deep_merge!(rxno: list.first(max)) if name == 'rxno'
data.deep_merge!(chmo: list.first(max)) if name == 'chmo'
data[name.to_sym] = [term_id]
end
current_user.profile.update!(**{data: data})
current_user.profile.update!(**{ data: data })
end
end
end
......@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import UserStore from './stores/UserStore';
const filterTreeNode = (input, child) => {
return String(child.props.search).indexOf(input) !== -1;
return String(child.props.search && child.props.search.toLowerCase()).indexOf(input && input.toLowerCase()) !== -1;
};
export default class OlsTreeSelect extends Component {
constructor(props) {
......
......@@ -141,15 +141,11 @@ export default class UsersFetcher {
return promise;
}
static fetchOls(name, is_enabled=true) {
const promise = fetch(`/api/v1/ols_terms/list.json?name=${name}&is_enabled=${is_enabled}`, {
static fetchOls(name, edited = true) {
return fetch(`/api/v1/ols_terms/list.json?name=${name}&edited=${edited}`, {
credentials: 'same-origin'
})
.then(response => response.json())
}).then(response => response.json())
.then(json => json)
.catch((errorMessage) => {
console.log(errorMessage);
});
return promise;
.catch((errorMessage) => { console.log(errorMessage); });
}
}
......@@ -19,6 +19,10 @@ class OlsTerm < ActiveRecord::Base
INSERT INTO ols_terms (#{COLUMNS.join(',')}) VALUES
SQL
SQL_BULK_SWITCH = <<~SQL
UPDATE ols_terms SET is_enabled = ? WHERE id in (?)
SQL
BULK_INSERT_STRING_SIZE = SQL_BULK_INSERT.size
INSERT_VALUE_QUESTION_MARKS = "(#{Array.new(COLUMNS.size){'?'}.join(',')})"
......@@ -39,12 +43,13 @@ class OlsTerm < ActiveRecord::Base
json_doc = Hash.from_xml(xml_doc).as_json
all_terms = json_doc['RDF']['Class']
version_info = json_doc['RDF']['Ontology']
all_terms.each_slice(50) do |nodes|
all_terms.each_slice(100) do |nodes|
create_from_owl_nodes(nodes, owl_name, version_info: version_info)
end
rebuilt_ancestry_by_owl_name(owl_name)
end
# bulk insert from a slice of owl nodes
def create_from_owl_nodes(nodes, owl_name, version_info: {})
values = []
created_at = Time.now
......@@ -54,29 +59,31 @@ class OlsTerm < ActiveRecord::Base
subClassTermId = extract_subclass_term_id_from_node(node)
if (synonyms = node['hasExactSynonym'].presence)
if synonyms.class == String
if synonyms.is_a?(String)
synonym = synonyms
synonyms = [synonyms]
else
else # synonyms.is_a?(Array)
synonym = synonyms.sort_by(&:length)[0]
end
end
label = node['label'].is_a?(String)? node['label'] : node['label'][0]
# to correspond in order to SQL_BULK_INSERT listed columns
value = [
owl_name,
node['id'],
subClassTermId,
node['label'],
node['label'].is_a?(String)? node['label'] : node['label'].join(' - '), #[0],
synonym,
synonyms.to_json,
node['IAO_0000115'],
node['IAO_0000115'].is_a?(Array)? node['IAO_0000115'].join(' - ') : node['IAO_0000115'],
{ "klass": node, "version": version_info }.to_json,
created_at,
created_at
]
next unless value.compact.present?
values << sanitize_sql([SQL_BULK_INSERT_SANITIZE] + value)[BULK_INSERT_STRING_SIZE..-1]
end
ActiveRecord::Base.connection.exec_query("#{SQL_BULK_INSERT} #{values.join(',')}")
ActiveRecord::Base.connection.exec_query("#{SQL_BULK_INSERT} #{values.join(',')}") if values.present?
end
def rebuilt_ancestry_by_owl_name(owl_name)
......@@ -100,9 +107,28 @@ class OlsTerm < ActiveRecord::Base
a = args.slice(:owl_name, :term_id)
node = find_by(**a)
return unless node
([node] + node.descendants).each { |n| n.update!(is_enabled: false) }
node_ids = [node.id] + node.descendants.pluck(:id)
disable_by_ids(node_ids)
end
def disable_by_ids(ids)
switch_by_ids(ids, false)
end
def enable_by_ids(ids)
switch_by_ids(ids, true)
end
def switch_by_ids(ids, bool = false)
ids = [ids].flatten
sanitized_sql = sanitize_sql([SQL_BULK_SWITCH, bool, ids])
ActiveRecord::Base.connection.exec_query(sanitized_sql)
end
def write_public_file(owl_name, owl)
file_path = Rails.public_path.join('ontologies', "#{owl_name}.json")
File.write(file_path, owl.to_json)
end
private
def build_direct_parent_ancestry(owl_name)
......
......@@ -3,8 +3,7 @@ class DefaultRecentProfile < ActiveRecord::Migration
CHMO = ['CHMO:0000593', 'CHMO:0000595', 'CHMO:0000470', 'CHMO:0001075', 'CHMO:0000497', 'CHMO:0001009', 'CHMO:0000630', 'CHMO:0001007', 'CHMO:0000156', 'BFO:0000015']
def up
us = User.all
us.each do |u|
Person.find_each do |u|
profile = u.profile
data = profile.data || {}
data.merge!(chmo: CHMO)
......@@ -14,8 +13,7 @@ class DefaultRecentProfile < ActiveRecord::Migration
end
def down
us = User.all
us.each do |u|
Person.find_each do |u|
profile = u.profile
data = profile.data
next if data.nil?
......
class CurateProfileRecentOwl < ActiveRecord::Migration
def change
Profile.find_each do |profile|
data = profile.data
# break unless defined? OlsTerm
%w[chmo rxno].each do |owl_name|
next unless data[owl_name].present?
recent_terms = []
data[owl_name].each do |term|
unless term.is_a?(String)
recent_terms << term
next
end
t = OlsTerm.find_by(term_id: term)
new_term = {
'owl_name' => owl_name,
'term_id' => term,
'title' => t.label,
'synonym' => t.synonym,
'synonyms' => t.synonyms,
'search' => "#{term} | #{t.label} (#{[t.synonyms].flatten.join(',')})",
'value' => "#{term} | #{t.label} (#{t.synonym})",
}
recent_terms << new_term
end
data[owl_name] = recent_terms
end
profile.update(data: data)
end
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20190708112047) do
ActiveRecord::Schema.define(version: 20190712090136) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment