Skip to content

Commit

Permalink
Chemotion Repository 2.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
cllde8 authored and phuang26 committed Nov 6, 2024
1 parent ed3cf05 commit 5b62524
Show file tree
Hide file tree
Showing 167 changed files with 5,669 additions and 3,600 deletions.
3 changes: 0 additions & 3 deletions .env.production.example
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,3 @@ SENTRY_BACKEND_SAMPLE_RATE=0.5
SENTRY_FRONTEND_DSN=https://sentryserver/OTHER-ID
SENTRY_FRONTEND_SAMPLE_RATE=1.0


## For REPO
MATOMO_URL=https://matomo.tld
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ gem 'kaminari'
gem 'kaminari-grape'
gem 'ketcherails', git: 'https://github.com/complat/ketcher-rails.git', branch: 'upgrade-to-rails-6'

gem 'labimotion', '1.3.2'
gem 'labimotion', '1.4.0.1'

gem 'mimemagic', '0.3.10'
gem 'mime-types'
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ GEM
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
labimotion (1.3.2)
labimotion (1.4.0.1)
rails (~> 6.1.7)
latex-decode (0.4.0)
launchy (2.5.0)
Expand Down Expand Up @@ -918,7 +918,7 @@ DEPENDENCIES
kaminari
kaminari-grape
ketcherails!
labimotion (= 1.3.2)
labimotion (= 1.4.0.1)
launchy
listen
memory_profiler
Expand Down
4 changes: 2 additions & 2 deletions app/api/chemotion/element_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ class ElementAPI < Grape::API
elements = @collection.send(element + 's').by_ui_state(params[element])

elements.each do |el|
pub = el.publication
pub = el.publication if el.respond_to?(:publication)

next if pub.nil?
pub.update_state(Publication::STATE_DECLINED)
pub.process_element(Publication::STATE_DECLINED)
pub.inform_users(Publication::STATE_DECLINED, current_user.id)
pub.process_new_state_job(Publication::STATE_DECLINED, current_user.id)
end
deleted[element] = elements.destroy_all.map(&:id)

Expand Down
105 changes: 59 additions & 46 deletions app/api/chemotion/public_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ class PublicAPI < Grape::API
end
end


desc 'Public initialization'
params do
end
get 'initialize' do
{
molecule_viewer: Matrice.molecule_viewer
molecule_viewer: Matrice.molecule_viewer,
u: Rails.configuration.u || {},
}
end

Expand Down Expand Up @@ -377,8 +375,9 @@ def query_embargo(name)
optional :pages, type: Integer, desc: 'pages'
optional :per_page, type: Integer, desc: 'per page'
optional :adv_flag, type: Boolean, desc: 'advanced search?'
optional :adv_type, type: String, desc: 'advanced search type', values: %w[Authors Ontologies Embargo]
optional :adv_type, type: String, desc: 'advanced search type', values: %w[Authors Ontologies Embargo Label]
optional :adv_val, type: Array[String], desc: 'advanced search value', regexp: /^(\d+|([[:alpha:]]+:\d+))$/
optional :label_val, type: Integer, desc: 'label_val'
optional :req_xvial, type: Boolean, default: false, desc: 'xvial is required or not'
end
paginate per_page: 10, offset: 0, max_per_page: 100
Expand Down Expand Up @@ -407,13 +406,18 @@ def query_embargo(name)
SQL
end
end
if params[:adv_type] == 'Label' && params[:label_val].present?
label_search = <<~SQL
and pub.taggable_data->'user_labels' @> '#{params[:label_val]}'
SQL
end
sample_join = <<~SQL
INNER JOIN (
SELECT molecule_id, published_at max_published_at, sample_svg_file, id as sid
FROM (
SELECT samples.*, pub.published_at, rank() OVER (PARTITION BY molecule_id order by pub.published_at desc) as rownum
FROM samples, publications pub
WHERE pub.element_type='Sample' and pub.element_id=samples.id and pub.deleted_at ISNULL
WHERE pub.element_type='Sample' and pub.element_id=samples.id and pub.deleted_at ISNULL #{label_search}
and samples.id IN (
SELECT samples.id FROM samples
INNER JOIN collections_samples cs on cs.collection_id = #{public_collection_id} and cs.sample_id = samples.id and cs.deleted_at ISNULL
Expand Down Expand Up @@ -465,8 +469,9 @@ def query_embargo(name)
optional :pages, type: Integer, desc: 'pages'
optional :per_page, type: Integer, desc: 'per page'
optional :adv_flag, type: Boolean, desc: 'is it advanced search?'
optional :adv_type, type: String, desc: 'advanced search type', values: %w[Authors Ontologies Embargo]
optional :adv_type, type: String, desc: 'advanced search type', values: %w[Authors Ontologies Embargo Label]
optional :adv_val, type: Array[String], desc: 'advanced search value', regexp: /^(\d+|([[:alpha:]]+:\d+))$/
optional :label_val, type: Integer, desc: 'label_val'
optional :scheme_only, type: Boolean, desc: 'is it a scheme-only reaction?', default: false
end
paginate per_page: 10, offset: 0, max_per_page: 100
Expand Down Expand Up @@ -518,6 +523,9 @@ def query_embargo(name)
else
col_scope = Collection.public_collection.reactions.joins(adv_search).joins(:publication).select(embargo_sql).order('publications.published_at desc')
end
if params[:adv_type] == 'Label' && params[:label_val].present?
col_scope = col_scope.where("publications.taggable_data->'user_labels' @> '?'", params[:label_val])
end
reset_pagination_page(col_scope)
list = paginate(col_scope)
entities = Entities::ReactionPublicationListEntity.represent(list, serializable: true)
Expand Down Expand Up @@ -574,8 +582,8 @@ def query_embargo(name)
r_pub = Publication.where(element_type: 'Reaction', state: 'completed').order(:published_at).last
reaction = r_pub.element

{ last_published: { sample: { id: sample.id, sample_svg_file: sample.sample_svg_file, molecule: sample.molecule, tag: s_pub.taggable_data, contributor: User.find(s_pub.published_by).name },
reaction: { id: reaction.id, reaction_svg_file: reaction.reaction_svg_file, tag: r_pub.taggable_data, contributor: User.find(r_pub.published_by).name } } }
{ last_published: { sample: { id: sample.id, sample_svg_file: sample.sample_svg_file, molecule: sample.molecule, tag: s_pub.taggable_data, contributor: User.with_deleted.find(s_pub.published_by).name },
reaction: { id: reaction.id, reaction_svg_file: reaction.reaction_svg_file, tag: r_pub.taggable_data, contributor: User.with_deleted.find(r_pub.published_by).name } } }
end
end

Expand Down Expand Up @@ -638,7 +646,6 @@ def query_embargo(name)
end

resource :embargo do
helpers RepositoryHelpers
desc "Return PUBLISHED serialized collection"
params do
requires :id, type: Integer, desc: "collection id"
Expand All @@ -652,15 +659,18 @@ def query_embargo(name)


resource :col_list do
helpers RepositoryHelpers
after_validation do
@embargo_collection = Collection.find(params[:collection_id])
@pub = @embargo_collection.publication
error!('401 Unauthorized', 401) if @pub.nil?

if @pub.state != 'completed'
error!('401 Unauthorized', 401) unless current_user.present? && (User.reviewer_ids.include?(current_user.id) || @pub.published_by == current_user.id || current_user.type == 'Anonymous')
is_reviewer = User.reviewer_ids.include?(current_user&.id)
is_submitter = (@pub.published_by == current_user&.id || @pub.review&.dig('submitters')&.include?(current_user&.id)) && SyncCollectionsUser.find_by(user_id: current_user.id, collection_id: @embargo_collection.id).present?
is_anonymous = current_user&.type == 'Anonymous' && SyncCollectionsUser.find_by(user_id: current_user.id, collection_id: @embargo_collection.id).present?
error!('401 Unauthorized', 401) unless current_user.present? && (is_reviewer || is_submitter || is_anonymous)
end
@is_reviewer = User.reviewer_ids.include?(current_user&.id)
end
get do
anasql = <<~SQL
Expand All @@ -672,7 +682,7 @@ def query_embargo(name)
elements = []
list.each do |e|
element_type = e.element&.class&.name
u = User.find(e.published_by) unless e.published_by.nil?
u = User.with_deleted.find(e.published_by) unless e.published_by.nil?
svg_file = e.element.sample_svg_file if element_type == 'Sample'
title = e.element.short_label if element_type == 'Sample'

Expand All @@ -685,13 +695,12 @@ def query_embargo(name)
published_by: u&.name, submit_at: e.created_at, state: e.state, scheme_only: scheme_only, ana_cnt: e.ana_cnt
)
end
is_reviewer = User.reviewer_ids.include?(current_user&.id)
{ elements: elements, embargo: @pub, embargo_id: params[:collection_id], current_user: { id: current_user&.id, type: current_user&.type, is_reviewer: is_reviewer } }

{ elements: elements, embargo: @pub, embargo_id: params[:collection_id], current_user: { id: current_user&.id, type: current_user&.type, is_reviewer: @is_reviewer } }
end
end

resource :col_element do
helpers RepositoryHelpers
params do
requires :collection_id, type: Integer, desc: "collection id"
requires :el_id, type: Integer, desc: "element id"
Expand All @@ -717,7 +726,6 @@ def query_embargo(name)
end

resource :reaction do
helpers RepositoryHelpers
desc "Return PUBLISHED serialized reaction"
params do
requires :id, type: Integer, desc: "Reaction id"
Expand All @@ -738,16 +746,16 @@ def query_embargo(name)
end

resource :molecule do
helpers RepositoryHelpers
desc 'Return serialized molecule with list of PUBLISHED dataset'
params do
requires :id, type: Integer, desc: 'Molecule id'
optional :adv_flag, type: Boolean, desc: 'advanced search flag'
optional :adv_type, type: String, desc: 'advanced search type', allow_blank: true, values: %w[Authors Ontologies Embargo]
optional :adv_type, type: String, desc: 'advanced search type', allow_blank: true, values: %w[Authors Ontologies Embargo Label]
optional :adv_val, type: Array[String], desc: 'advanced search value', regexp: /^(\d+|([[:alpha:]]+:\d+))$/
optional :label_val, type: Integer, desc: 'label_val'
end
get do
get_pub_molecule(params[:id], params[:adv_flag], params[:adv_type], params[:adv_val])
get_pub_molecule(params[:id], params[:adv_flag], params[:adv_type], params[:adv_val], params[:label_val])
end
end

Expand Down Expand Up @@ -895,11 +903,33 @@ def query_embargo(name)
error!('404 Is not published yet', 404) unless @publication&.state&.include?('completed')
end
get do
Base64.encode64(@attachment.read_thumbnail) if @attachment.thumb
if @attachment.thumb
thumbnail = @attachment.read_thumbnail
thumbnail ? Base64.encode64(thumbnail) : nil
else
nil
end
end
end
end

resource :export_metadata do
desc 'Get dataset metadata of publication'
params do
requires :id, type: Integer, desc: "Dataset Id"
end
before do
@dataset_id = params[:id]
@container = Container.find_by(id: @dataset_id)
element = @container.root.containable
@publication = Publication.find_by(element: element, state: 'completed') if element.present?
error!('404 Publication not found', 404) unless @publication.present?
end
get do
prepare_and_export_dataset(@container.id)
end
end

resource :metadata do
desc "batch download metadata"
params do
Expand All @@ -916,11 +946,11 @@ def query_embargo(name)
result = declared(params, include_missing: false)
list = []
limit = params[:limit] - params[:offset] > 1000 ? params[:offset] + 1000 : params[:limit]
scope = Publication.where(element_type: params[:type], state: 'completed')
scope = Publication.includes(:doi).where(element_type: params[:type], state: 'completed')
scope = scope.where('published_at >= ?', params[:date_from]) if params[:date_from].present?
scope = scope.where('published_at <= ?', params[:date_to]) if params[:date_to].present?
publications = scope.order(:published_at).offset(params[:offset]).limit(limit)
publications.map do |publication|
publications.each do |publication|
inchikey = publication&.doi&.suffix
list.push("#{service_url}#{api_url}#{inchikey}") if inchikey.present?
end
Expand All @@ -929,23 +959,6 @@ def query_embargo(name)
result
end

resource :export do
desc 'Get dataset metadata of publication'
params do
requires :id, type: Integer, desc: "Dataset Id"
end
before do
@dataset_id = params[:id]
@container = Container.find_by(id: @dataset_id)
element = @container.root.containable
@publication = Publication.find_by(element: element, state: 'completed') if element.present?
error!('404 Publication not found', 404) unless @publication.present?
end
get do
prepare_and_export_dataset(@container.id)
end
end

desc "metadata of publication"
params do
optional :id, type: Integer, desc: "Id"
Expand Down Expand Up @@ -1001,15 +1014,15 @@ def query_embargo(name)
end
end

resource :service do
desc 'convert molfile to 3d'
resource :represent do
desc 'represent molfile structure'
params do
requires :molfile, type: String, desc: 'Molecule molfile'
requires :mol, type: String, desc: 'Molecule molfile'
end
post :convert do
convert_to_3d(params[:molfile])
post :structure do
represent_structure(params[:mol])
rescue StandardError => e
return { msg: { level: 'error', message: e } }
return { molfile: params[:mol], msg: { level: 'error', message: e } }
end
end
end
Expand Down
13 changes: 11 additions & 2 deletions app/api/chemotion/reaction_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class ReactionAPI < Grape::API
helpers ParamsHelpers
helpers LiteratureHelpers
helpers ProfileHelpers
helpers UserLabelHelpers

resource :reactions do
desc 'Return serialized reactions'
Expand All @@ -17,6 +18,7 @@ class ReactionAPI < Grape::API
optional :sync_collection_id, type: Integer, desc: 'SyncCollectionsUser id'
optional :from_date, type: Integer, desc: 'created_date from in ms'
optional :to_date, type: Integer, desc: 'created_date to in ms'
optional :user_label, type: Integer, desc: 'user label'
optional :filter_created_at, type: Boolean, desc: 'filter by created at or updated at'
optional :sort_column, type: String, desc: 'sort by created_at, updated_at, rinchi_short_key, or rxno',
values: %w[created_at updated_at rinchi_short_key rxno],
Expand Down Expand Up @@ -52,17 +54,19 @@ class ReactionAPI < Grape::API

from = params[:from_date]
to = params[:to_date]
user_label = params[:user_label]
by_created_at = params[:filter_created_at] || false

sort_column = params[:sort_column].presence || 'created_at'
sort_direction = params[:sort_direction].presence ||
(%w[created_at updated_at].include?(sort_column) ? 'DESC' : 'ASC')

scope = scope.includes_for_list_display.order("#{sort_column} #{sort_direction}")
scope = scope.includes_for_list_display.order("reactions.#{sort_column} #{sort_direction}")
scope = scope.created_time_from(Time.at(from)) if from && by_created_at
scope = scope.created_time_to(Time.at(to) + 1.day) if to && by_created_at
scope = scope.updated_time_from(Time.at(from)) if from && !by_created_at
scope = scope.updated_time_to(Time.at(to) + 1.day) if to && !by_created_at
scope = scope.by_user_label(user_label) if user_label

reset_pagination_page(scope)

Expand Down Expand Up @@ -158,11 +162,11 @@ class ReactionAPI < Grape::API

requires :materials, type: Hash
optional :literatures, type: Hash

requires :container, type: Hash
optional :duration, type: String
optional :rxno, type: String
optional :segments, type: Array
optional :user_labels, type: Array
optional :variations, type: [Hash]
end
route_param :id do
Expand All @@ -175,6 +179,8 @@ class ReactionAPI < Grape::API
put do
reaction = @reaction
attributes = declared(params, include_missing: false)
update_element_labels(reaction, attributes[:user_labels], current_user.id)
attributes.delete(:user_labels)
materials = attributes.delete(:materials)
attributes.delete(:literatures)
attributes.delete(:id)
Expand Down Expand Up @@ -224,6 +230,7 @@ class ReactionAPI < Grape::API
optional :origin, type: Hash
optional :reaction_svg_file, type: String
optional :segments, type: Array
optional :user_labels, type: Array
requires :materials, type: Hash
optional :literatures, type: Hash
requires :container, type: Hash
Expand All @@ -241,6 +248,7 @@ class ReactionAPI < Grape::API
container_info = params[:container]
attributes.delete(:container)
attributes.delete(:segments)
attributes.delete(:user_labels)

collection = current_user.collections.where(id: collection_id).take
attributes[:created_by] = current_user.id
Expand Down Expand Up @@ -275,6 +283,7 @@ class ReactionAPI < Grape::API
end
reaction.container = update_datamodel(container_info)
reaction.save!
update_element_labels(reaction, params[:user_labels], current_user.id)
reaction.save_segments(segments: params[:segments], current_user_id: current_user.id)
CollectionsReaction.create(reaction: reaction, collection: collection) if collection.present?

Expand Down
Loading

0 comments on commit 5b62524

Please sign in to comment.