labimotion 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/labimotion/api.rb +19 -0
- data/lib/labimotion/apis/converter_api.rb +68 -0
- data/lib/labimotion/apis/generic_dataset_api.rb +50 -0
- data/lib/labimotion/apis/generic_element_api.rb +339 -0
- data/lib/labimotion/apis/labimotion_hub_api.rb +53 -0
- data/lib/labimotion/apis/segment_api.rb +144 -0
- data/lib/labimotion/entities/application_entity.rb +88 -0
- data/lib/labimotion/entities/dataset_entity.rb +16 -0
- data/lib/labimotion/entities/dataset_klass_entity.rb +9 -0
- data/lib/labimotion/entities/element_entity.rb +108 -0
- data/lib/labimotion/entities/element_klass_entity.rb +10 -0
- data/lib/labimotion/entities/element_revision_entity.rb +57 -0
- data/lib/labimotion/entities/eln_element_entity.rb +110 -0
- data/lib/labimotion/entities/generic_entity.rb +54 -0
- data/lib/labimotion/entities/generic_klass_entity.rb +14 -0
- data/lib/labimotion/entities/generic_public_entity.rb +25 -0
- data/lib/labimotion/entities/klass_revision_entity.rb +20 -0
- data/lib/labimotion/entities/segment_entity.rb +62 -0
- data/lib/labimotion/entities/segment_klass_entity.rb +8 -0
- data/lib/labimotion/entities/segment_revision_entity.rb +55 -0
- data/lib/labimotion/helpers/converter_helpers.rb +13 -0
- data/lib/labimotion/helpers/dataset_helpers.rb +38 -0
- data/lib/labimotion/helpers/element_helpers.rb +268 -0
- data/lib/labimotion/helpers/generic_helpers.rb +252 -0
- data/lib/labimotion/helpers/repository_helpers.rb +14 -0
- data/lib/labimotion/helpers/sample_association_helpers.rb +126 -0
- data/lib/labimotion/helpers/search_helpers.rb +62 -0
- data/lib/labimotion/helpers/segment_helpers.rb +97 -0
- data/lib/labimotion/libs/converter.rb +325 -0
- data/lib/labimotion/libs/export_dataset.rb +121 -0
- data/lib/labimotion/libs/nmr_mapper.rb +265 -0
- data/lib/labimotion/libs/nmr_mapper_repo.rb +263 -0
- data/lib/labimotion/libs/template_hub.rb +55 -0
- data/lib/labimotion/models/collections_element.rb +42 -0
- data/lib/labimotion/models/concerns/attachment_converter.rb +42 -0
- data/lib/labimotion/models/concerns/datasetable.rb +50 -0
- data/lib/labimotion/models/concerns/generic_klass_revisions.rb +39 -0
- data/lib/labimotion/models/concerns/generic_revisions.rb +43 -0
- data/lib/labimotion/models/concerns/segmentable.rb +74 -0
- data/lib/labimotion/models/dataset.rb +14 -0
- data/lib/labimotion/models/dataset_klass.rb +25 -0
- data/lib/labimotion/models/dataset_klasses_revision.rb +9 -0
- data/lib/labimotion/models/datasets_revision.rb +9 -0
- data/lib/labimotion/models/element.rb +121 -0
- data/lib/labimotion/models/element_klass.rb +25 -0
- data/lib/labimotion/models/element_klasses_revision.rb +9 -0
- data/lib/labimotion/models/elements_element.rb +11 -0
- data/lib/labimotion/models/elements_revision.rb +8 -0
- data/lib/labimotion/models/elements_sample.rb +11 -0
- data/lib/labimotion/models/segment.rb +14 -0
- data/lib/labimotion/models/segment_klass.rb +24 -0
- data/lib/labimotion/models/segment_klasses_revision.rb +9 -0
- data/lib/labimotion/models/segments_revision.rb +9 -0
- data/lib/labimotion/utils/con_state.rb +13 -0
- data/lib/labimotion/utils/export.rb +112 -0
- data/lib/labimotion/utils/import.rb +186 -0
- data/lib/labimotion/utils/search.rb +112 -0
- data/lib/labimotion/utils/serializer.rb +78 -0
- data/lib/labimotion/version.rb +6 -0
- data/lib/labimotion.rb +95 -0
- metadata +119 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Datasetable concern
|
4
|
+
|
5
|
+
module Labimotion
|
6
|
+
## Datasetable concern
|
7
|
+
module Datasetable
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
has_one :dataset, as: :element, class_name: 'Labimotion::Dataset'
|
12
|
+
end
|
13
|
+
|
14
|
+
def not_dataset?
|
15
|
+
self.class.name == 'Container' && container_type != 'dataset'
|
16
|
+
end
|
17
|
+
|
18
|
+
def save_dataset(**args)
|
19
|
+
return if not_dataset?
|
20
|
+
|
21
|
+
klass = Labimotion::DatasetKlass.find_by(id: args[:dataset_klass_id])
|
22
|
+
uuid = SecureRandom.uuid
|
23
|
+
props = args[:properties]
|
24
|
+
props['eln'] = Chemotion::Application.config.version
|
25
|
+
props['labimotion'] = Labimotion::VERSION
|
26
|
+
ds = Labimotion::Dataset.find_by(element_type: self.class.name, element_id: id)
|
27
|
+
if ds.present? && (ds.klass_uuid != props['klass_uuid'] || ds.properties != props)
|
28
|
+
props['uuid'] = uuid
|
29
|
+
props['eln'] = Chemotion::Application.config.version
|
30
|
+
props['labimotion'] = Labimotion::VERSION
|
31
|
+
props['klass'] = 'Dataset'
|
32
|
+
ds.update!(properties_release: klass.properties_release, uuid: uuid, dataset_klass_id: args[:dataset_klass_id], properties: props, klass_uuid: props['klass_uuid'])
|
33
|
+
end
|
34
|
+
return if ds.present?
|
35
|
+
|
36
|
+
props['uuid'] = uuid
|
37
|
+
props['klass_uuid'] = klass.uuid
|
38
|
+
props['eln'] = Chemotion::Application.config.version
|
39
|
+
props['labimotion'] = Labimotion::VERSION
|
40
|
+
props['klass'] = 'Dataset'
|
41
|
+
Labimotion::Dataset.create!(properties_release: klass.properties_release, uuid: uuid, dataset_klass_id: args[:dataset_klass_id], element_type: self.class.name, element_id: id, properties: props, klass_uuid: klass.uuid)
|
42
|
+
end
|
43
|
+
|
44
|
+
def destroy_datasetable
|
45
|
+
return if not_dataset?
|
46
|
+
|
47
|
+
Labimotion::Dataset.where(element_type: self.class.name, element_id: id).destroy_all
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labimotion
|
4
|
+
module GenericKlassRevisions
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
included do
|
7
|
+
# has_many :element_klasses_revisions, dependent: :destroy
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_klasses_revision(user_id=0)
|
11
|
+
properties_release = properties_template
|
12
|
+
# (properties_release['layers'] || {}).keys.each do |key|
|
13
|
+
# properties_release['layers'][key]['layer'] = properties_release['layers'][key]['key']
|
14
|
+
# end
|
15
|
+
|
16
|
+
if properties_release['flow'].present?
|
17
|
+
elements = (properties_release['flow']['elements'] || []).map do |el|
|
18
|
+
if el['data'].present? && el['data']['lKey'].present?
|
19
|
+
layer = properties_release['layers'][el['data']['lKey']]
|
20
|
+
el['data']['layer'] = layer if layer.present?
|
21
|
+
end
|
22
|
+
el
|
23
|
+
end
|
24
|
+
properties_release['flow']['elements'] = elements
|
25
|
+
end
|
26
|
+
|
27
|
+
self.update!({ uuid: properties_template['uuid'], properties_release: properties_release, released_at: DateTime.now })
|
28
|
+
reload
|
29
|
+
attributes = {
|
30
|
+
released_by: user_id,
|
31
|
+
uuid: uuid,
|
32
|
+
properties_release: properties_release,
|
33
|
+
released_at: released_at
|
34
|
+
}
|
35
|
+
attributes["#{self.class.name.underscore.split('/').last}_id"] = id
|
36
|
+
"#{self.class.name}esRevision".constantize.create(attributes)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# GenericRevisions concern
|
4
|
+
module Labimotion
|
5
|
+
module GenericRevisions
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
included do
|
8
|
+
after_create :create_vault
|
9
|
+
after_update :save_to_vault
|
10
|
+
before_destroy :delete_attachments
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_vault
|
14
|
+
save_to_vault unless self.class.name == 'Labimotion::Element'
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_to_vault
|
18
|
+
attributes = {
|
19
|
+
uuid: uuid,
|
20
|
+
klass_uuid: klass_uuid,
|
21
|
+
properties: properties,
|
22
|
+
properties_release: properties_release
|
23
|
+
}
|
24
|
+
attributes["#{self.class.name.downcase.split('::').last}_id"] = id
|
25
|
+
attributes['name'] = name if self.class.name == 'Labimotion::Element'
|
26
|
+
"#{self.class.name}sRevision".constantize.create(attributes)
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete_attachments
|
30
|
+
att_ids = []
|
31
|
+
properties && properties['layers']&.keys&.each do |key|
|
32
|
+
layer = properties['layers'][key]
|
33
|
+
field_uploads = layer['fields'].select { |ss| ss['type'] == 'upload' }
|
34
|
+
field_uploads.each do |field|
|
35
|
+
(field['value'] && field['value']['files'] || []).each do |file|
|
36
|
+
att_ids.push(file['aid']) unless file['aid'].nil?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
Attachment.where(id: att_ids, attachable_id: id, attachable_type: %w[ElementProps SegmentProps]).destroy_all
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labimotion
|
4
|
+
# Segmentable concern
|
5
|
+
module Segmentable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
included do
|
8
|
+
has_many :segments, as: :element, dependent: :destroy, class_name: 'Labimotion::Segment'
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy_segments(**args)
|
12
|
+
return if args[:segments].nil?
|
13
|
+
|
14
|
+
segments = save_segments(segments: args[:segments], current_user_id: args[:current_user_id])
|
15
|
+
segments.each do |segment|
|
16
|
+
properties = segment.properties
|
17
|
+
properties['layers'].keys.each do |key|
|
18
|
+
layer = properties['layers'][key]
|
19
|
+
field_uploads = layer['fields'].select { |ss| ss['type'] == 'upload' }
|
20
|
+
field_uploads&.each do |upload|
|
21
|
+
idx = properties['layers'][key]['fields'].index(upload)
|
22
|
+
files = upload["value"] && upload["value"]["files"]
|
23
|
+
files&.each_with_index do |fi, fdx|
|
24
|
+
aid = properties['layers'][key]['fields'][idx]['value']['files'][fdx]['aid']
|
25
|
+
unless aid.nil?
|
26
|
+
copied_att = Attachment.find(aid)&.copy(attachable_type: 'SegmentProps', attachable_id: segment.id, transferred: true)
|
27
|
+
unless copied_att.nil?
|
28
|
+
copied_att.save!
|
29
|
+
properties['layers'][key]['fields'][idx]['value']['files'][fdx]['aid'] = copied_att.id
|
30
|
+
properties['layers'][key]['fields'][idx]['value']['files'][fdx]['uid'] = copied_att.identifier
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
segment.update!(properties: properties)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def save_segments(**args) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
41
|
+
return if args[:segments].nil?
|
42
|
+
|
43
|
+
segments = []
|
44
|
+
args[:segments].each do |seg|
|
45
|
+
klass = Labimotion::SegmentKlass.find_by(id: seg['segment_klass_id'])
|
46
|
+
uuid = SecureRandom.uuid
|
47
|
+
props = seg['properties']
|
48
|
+
props['eln'] = Chemotion::Application.config.version
|
49
|
+
props['labimotion'] = Labimotion::VERSION
|
50
|
+
segment = Labimotion::Segment.find_by(element_type: self.class.name.split('::').last, element_id: self.id, segment_klass_id: seg['segment_klass_id'])
|
51
|
+
if segment.present? && (segment.klass_uuid != props['klass_uuid'] || segment.properties != props)
|
52
|
+
props['uuid'] = uuid
|
53
|
+
props['eln'] = Chemotion::Application.config.version
|
54
|
+
props['labimotion'] = Labimotion::VERSION
|
55
|
+
props['klass'] = 'Segment'
|
56
|
+
|
57
|
+
segment.update!(properties_release: klass.properties_release, properties: props, uuid: uuid, klass_uuid: props['klass_uuid'])
|
58
|
+
segments.push(segment)
|
59
|
+
end
|
60
|
+
next if segment.present?
|
61
|
+
|
62
|
+
props['uuid'] = uuid
|
63
|
+
props['klass_uuid'] = klass.uuid
|
64
|
+
props['eln'] = Chemotion::Application.config.version
|
65
|
+
props['labimotion'] = Labimotion::VERSION
|
66
|
+
props['klass'] = 'Segment'
|
67
|
+
|
68
|
+
segment = Labimotion::Segment.create!(properties_release: klass.properties_release, segment_klass_id: seg['segment_klass_id'], element_type: self.class.name.split('::').last, element_id: self.id, properties: props, created_by: args[:current_user_id], uuid: uuid, klass_uuid: klass.uuid)
|
69
|
+
segments.push(segment)
|
70
|
+
end
|
71
|
+
segments
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'labimotion/models/concerns/generic_revisions'
|
3
|
+
|
4
|
+
# ## This is the first version of the dataset class
|
5
|
+
module Labimotion
|
6
|
+
# ## This is the first version of the dataset class
|
7
|
+
class Dataset < ApplicationRecord
|
8
|
+
self.table_name = :datasets
|
9
|
+
acts_as_paranoid
|
10
|
+
include GenericRevisions
|
11
|
+
belongs_to :dataset_klass, class_name: 'Labimotion::DatasetKlass'
|
12
|
+
belongs_to :element, polymorphic: true, class_name: 'Labimotion::Element'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'labimotion/models/concerns/generic_klass_revisions'
|
3
|
+
|
4
|
+
module Labimotion
|
5
|
+
class DatasetKlass < ApplicationRecord
|
6
|
+
acts_as_paranoid
|
7
|
+
self.table_name = :dataset_klasses
|
8
|
+
include GenericKlassRevisions
|
9
|
+
has_many :datasets, dependent: :destroy, class_name: 'Labimotion::Dataset'
|
10
|
+
has_many :dataset_klasses_revisions, dependent: :destroy, class_name: 'Labimotion::DatasetKlassesRevision'
|
11
|
+
|
12
|
+
def self.init_seeds
|
13
|
+
seeds_path = File.join(Rails.root, 'db', 'seeds', 'json', 'dataset_klasses.json')
|
14
|
+
seeds = JSON.parse(File.read(seeds_path))
|
15
|
+
|
16
|
+
seeds['chmo'].each do |term|
|
17
|
+
next if Labimotion::DatasetKlass.where(ols_term_id: term['id']).count.positive?
|
18
|
+
|
19
|
+
attributes = { ols_term_id: term['id'], label: "#{term['label']} (#{term['synonym']})", desc: "#{term['label']} (#{term['synonym']})", place: term['position'], created_by: Admin.first&.id || 0 }
|
20
|
+
Labimotion::DatasetKlass.create!(attributes)
|
21
|
+
end
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'labimotion/models/concerns/generic_revisions'
|
3
|
+
require 'labimotion/models/concerns/segmentable'
|
4
|
+
|
5
|
+
module Labimotion
|
6
|
+
class Element < ApplicationRecord
|
7
|
+
acts_as_paranoid
|
8
|
+
self.table_name = :elements
|
9
|
+
include PgSearch
|
10
|
+
include ElementUIStateScopes
|
11
|
+
include Collectable
|
12
|
+
## include AnalysisCodes
|
13
|
+
include Taggable
|
14
|
+
include Segmentable
|
15
|
+
include GenericRevisions
|
16
|
+
|
17
|
+
multisearchable against: %i[name short_label]
|
18
|
+
|
19
|
+
pg_search_scope :search_by_substring, against: %i[name short_label], using: { trigram: { threshold: 0.0001 } }
|
20
|
+
|
21
|
+
attr_accessor :can_copy
|
22
|
+
|
23
|
+
scope :by_name, ->(query) { where('name ILIKE ?', "%#{sanitize_sql_like(query)}%") }
|
24
|
+
scope :by_short_label, ->(query) { where('short_label ILIKE ?', "%#{sanitize_sql_like(query)}%") }
|
25
|
+
scope :by_klass_id_short_label, ->(klass_id, short_label) { where('element_klass_id = ? and short_label ILIKE ?', klass_id, "%#{sanitize_sql_like(short_label)}%") }
|
26
|
+
scope :by_sample_ids, ->(ids) { joins(:elements_samples).where('sample_id IN (?)', ids) }
|
27
|
+
scope :by_klass_id, ->(klass_id) { where('element_klass_id = ? ', klass_id) }
|
28
|
+
|
29
|
+
belongs_to :element_klass, class_name: 'Labimotion::ElementKlass'
|
30
|
+
|
31
|
+
has_many :collections_elements, inverse_of: :element, dependent: :destroy, class_name: 'Labimotion::CollectionsElement'
|
32
|
+
has_many :collections, through: :collections_elements
|
33
|
+
has_many :attachments, as: :attachable
|
34
|
+
has_many :elements_samples, dependent: :destroy, class_name: 'Labimotion::ElementsSample'
|
35
|
+
has_many :samples, through: :elements_samples, source: :sample
|
36
|
+
has_one :container, :as => :containable
|
37
|
+
has_many :elements_revisions, dependent: :destroy, class_name: 'Labimotion::ElementsRevision'
|
38
|
+
|
39
|
+
accepts_nested_attributes_for :collections_elements
|
40
|
+
|
41
|
+
scope :elements_created_time_from, ->(time) { where('elements.created_at >= ?', time) }
|
42
|
+
scope :elements_created_time_to, ->(time) { where('elements.created_at <= ?', time) }
|
43
|
+
scope :elements_updated_time_from, ->(time) { where('elements.updated_at >= ?', time) }
|
44
|
+
scope :elements_updated_time_to, ->(time) { where('elements.updated_at <= ?', time) }
|
45
|
+
|
46
|
+
belongs_to :creator, foreign_key: :created_by, class_name: 'User'
|
47
|
+
validates :creator, presence: true
|
48
|
+
|
49
|
+
has_many :elements_elements, foreign_key: :parent_id, class_name: 'Labimotion::ElementsElement'
|
50
|
+
has_many :elements, through: :elements_elements, source: :element, class_name: 'Labimotion::Element'
|
51
|
+
|
52
|
+
before_create :auto_set_short_label
|
53
|
+
after_create :update_counter
|
54
|
+
before_destroy :delete_attachment
|
55
|
+
|
56
|
+
|
57
|
+
def attachments
|
58
|
+
Attachment.where(attachable_id: self.id, attachable_type: 'Element')
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.get_associated_samples(element_ids)
|
62
|
+
Labimotion::ElementsSample.where(element_id: element_ids).pluck(:sample_id)
|
63
|
+
end
|
64
|
+
|
65
|
+
def analyses
|
66
|
+
container ? container.analyses : []
|
67
|
+
end
|
68
|
+
|
69
|
+
def auto_set_short_label
|
70
|
+
prefix = element_klass.klass_prefix
|
71
|
+
if creator.counters[element_klass.name].nil?
|
72
|
+
creator.counters[element_klass.name] = '0'
|
73
|
+
creator.update_columns(counters: creator.counters)
|
74
|
+
creator.reload
|
75
|
+
end
|
76
|
+
counter = creator.counters[element_klass.name].to_i.succ
|
77
|
+
self.short_label = "#{creator.initials}-#{prefix}#{counter}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def update_counter
|
81
|
+
creator.increment_counter element_klass.name
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.get_associated_elements(element_ids)
|
85
|
+
pids = Labimotion::Element.where(id: element_ids).pluck :id
|
86
|
+
get_ids = proc do |eids|
|
87
|
+
eids.each do |p|
|
88
|
+
cs = Labimotion::Element.find_by(id: p)&.elements.where.not(id: pids).pluck :id
|
89
|
+
next if cs.empty?
|
90
|
+
|
91
|
+
pids = (pids << cs).flatten.uniq
|
92
|
+
get_ids.call(cs)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
get_ids.call(pids)
|
96
|
+
pids
|
97
|
+
end
|
98
|
+
|
99
|
+
def thumb_svg
|
100
|
+
image_atts = attachments.select do |a_img|
|
101
|
+
a_img&.content_type&.match(Regexp.union(%w[jpg jpeg png tiff tif]))
|
102
|
+
end
|
103
|
+
|
104
|
+
attachment = image_atts[0] || attachments[0]
|
105
|
+
preview = attachment.read_thumbnail if attachment
|
106
|
+
preview && Base64.encode64(preview) || 'not available'
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def delete_attachment
|
112
|
+
if Rails.env.production?
|
113
|
+
attachments.each do |attachment|
|
114
|
+
attachment.delay(run_at: 96.hours.from_now, queue: 'attachment_deletion').destroy!
|
115
|
+
end
|
116
|
+
else
|
117
|
+
attachments.each(&:destroy!)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'labimotion/models/concerns/generic_klass_revisions'
|
3
|
+
|
4
|
+
module Labimotion
|
5
|
+
class ElementKlass < ApplicationRecord
|
6
|
+
acts_as_paranoid
|
7
|
+
self.table_name = :element_klasses
|
8
|
+
include GenericKlassRevisions
|
9
|
+
has_many :elements, dependent: :destroy, class_name: 'Labimotion::Element'
|
10
|
+
has_many :segment_klasses, dependent: :destroy, class_name: 'Labimotion::SegmentKlass'
|
11
|
+
has_many :element_klasses_revisions, dependent: :destroy, class_name: 'Labimotion::ElementKlassesRevision'
|
12
|
+
|
13
|
+
def self.gen_klasses_json
|
14
|
+
klasses = where(is_active: true, is_generic: true).order('place')&.pluck(:name) || []
|
15
|
+
rescue ActiveRecord::StatementInvalid, PG::ConnectionBad, PG::UndefinedTable
|
16
|
+
klasses = []
|
17
|
+
ensure
|
18
|
+
File.write(
|
19
|
+
Rails.root.join('config', 'klasses.json'),
|
20
|
+
klasses&.to_json || []
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
module Labimotion
|
3
|
+
class ElementsElement < ApplicationRecord
|
4
|
+
self.table_name = :elements_elements
|
5
|
+
acts_as_paranoid
|
6
|
+
belongs_to :element, class_name: 'Labimotion::Element'
|
7
|
+
belongs_to :parent, foreign_key: :parent_id, class_name: 'Labimotion::Element'
|
8
|
+
|
9
|
+
# include Tagging
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'labimotion/models/concerns/generic_revisions'
|
3
|
+
|
4
|
+
module Labimotion
|
5
|
+
class Segment < ApplicationRecord
|
6
|
+
acts_as_paranoid
|
7
|
+
self.table_name = :segments
|
8
|
+
include GenericRevisions
|
9
|
+
|
10
|
+
belongs_to :segment_klass, class_name: 'Labimotion::SegmentKlass'
|
11
|
+
belongs_to :element, polymorphic: true, class_name: 'Labimotion::Element'
|
12
|
+
has_many :segments_revisions, dependent: :destroy, class_name: 'Labimotion::SegmentsRevision'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'labimotion/models/concerns/generic_klass_revisions'
|
3
|
+
|
4
|
+
module Labimotion
|
5
|
+
class SegmentKlass < ApplicationRecord
|
6
|
+
self.table_name = :segment_klasses
|
7
|
+
acts_as_paranoid
|
8
|
+
include GenericKlassRevisions
|
9
|
+
belongs_to :element_klass, class_name: 'Labimotion::ElementKlass'
|
10
|
+
has_many :segments, dependent: :destroy, class_name: 'Labimotion::Segment'
|
11
|
+
has_many :segment_klasses_revisions, dependent: :destroy, class_name: 'Labimotion::SegmentKlassesRevision'
|
12
|
+
|
13
|
+
def self.gen_klasses_json
|
14
|
+
klasses = where(is_active: true)&.pluck(:name) || []
|
15
|
+
rescue ActiveRecord::StatementInvalid, PG::ConnectionBad, PG::UndefinedTable
|
16
|
+
klasses = []
|
17
|
+
ensure
|
18
|
+
File.write(
|
19
|
+
Rails.root.join('config', 'segment_klass.json'),
|
20
|
+
klasses&.to_json || []
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labimotion
|
4
|
+
## Export
|
5
|
+
class Export
|
6
|
+
|
7
|
+
def self.fetch_element_klasses(&fetch_many)
|
8
|
+
klasses = Labimotion::ElementKlass.where(is_active: true)
|
9
|
+
fetch_many.call(klasses, {'created_by' => 'User'})
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.fetch_segment_klasses(&fetch_many)
|
13
|
+
klasses = Labimotion::SegmentKlass.where(is_active: true)
|
14
|
+
fetch_many.call(klasses, {
|
15
|
+
'element_klass_id' => 'Labimotion::ElementKlass',
|
16
|
+
'created_by' => 'User'
|
17
|
+
})
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.fetch_dataset_klasses(&fetch_many)
|
21
|
+
klasses = Labimotion::DatasetKlass.where(is_active: true)
|
22
|
+
fetch_many.call(klasses, {'created_by' => 'User'})
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def self.fetch_segments(element, attachments, &fetch_one)
|
27
|
+
element_type = element.class.name
|
28
|
+
segments = Labimotion::Segment.where("element_id = ? AND element_type = ?", element.id, element_type)
|
29
|
+
segments.each do |segment|
|
30
|
+
# segment = fetch_properties(segment)
|
31
|
+
segment, attachments = Labimotion::Export.fetch_properties(segment, attachments, &fetch_one)
|
32
|
+
# fetch_one.call(segment.segment_klass.element_klass)
|
33
|
+
# fetch_one.call(segment.segment_klass, {
|
34
|
+
# 'element_klass_id' => 'Labimotion::ElementKlass'
|
35
|
+
# })
|
36
|
+
fetch_one.call(segment, {
|
37
|
+
'element_id' => segment.element_type,
|
38
|
+
'segment_klass_id' => 'Labimotion::SegmentKlass',
|
39
|
+
'created_by' => 'User'
|
40
|
+
})
|
41
|
+
end
|
42
|
+
[segments, attachments]
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.fetch_datasets(dataset, &fetch_one)
|
46
|
+
return if dataset.nil?
|
47
|
+
|
48
|
+
fetch_one.call(dataset, {
|
49
|
+
'element_id' => 'Container',
|
50
|
+
})
|
51
|
+
fetch_one.call(dataset, {
|
52
|
+
'element_id' => dataset.element_type,
|
53
|
+
'dataset_klass_id' => 'Labimotion::DatasetKlass',
|
54
|
+
})
|
55
|
+
[dataset]
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def self.fetch_properties(instance, attachments, &fetch_one)
|
60
|
+
properties = instance.properties
|
61
|
+
properties['layers'].keys.each do |key|
|
62
|
+
layer = properties['layers'][key]
|
63
|
+
|
64
|
+
# field_samples = layer['fields'].select { |ss| ss['type'] == 'drag_sample' } -- TODO for elements
|
65
|
+
# field_elements = layer['fields'].select { |ss| ss['type'] == 'drag_element' } -- TODO for elements
|
66
|
+
|
67
|
+
field_molecules = layer['fields'].select { |ss| ss['type'] == 'drag_molecule' }
|
68
|
+
field_molecules.each do |field|
|
69
|
+
idx = properties['layers'][key]['fields'].index(field)
|
70
|
+
id = field["value"] && field["value"]["el_id"] unless idx.nil?
|
71
|
+
mol = Molecule.find(id) unless id.nil?
|
72
|
+
properties['layers'][key]['fields'][idx]['value']['el_id'] = fetch_one.call(mol) unless mol.nil?
|
73
|
+
end
|
74
|
+
field_uploads = layer['fields'].select { |ss| ss['type'] == 'upload' }
|
75
|
+
field_uploads.each do |upload|
|
76
|
+
idx = properties['layers'][key]['fields'].index(upload)
|
77
|
+
files = upload["value"] && upload["value"]["files"]
|
78
|
+
files&.each_with_index do |fi, fdx|
|
79
|
+
att = Attachment.find(fi['aid'])
|
80
|
+
attachments += [att]
|
81
|
+
properties['layers'][key]['fields'][idx]['value']['files'][fdx]['aid'] = fetch_one.call(att, {'attachable_id' => 'Labimotion::Segment'}) unless att.nil?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
field_tables = properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
|
86
|
+
field_tables&.each do |field|
|
87
|
+
next unless field['sub_values'].present? && field['sub_fields'].present?
|
88
|
+
# field_table_samples = field['sub_fields'].select { |ss| ss['type'] == 'drag_sample' } -- not available yet
|
89
|
+
# field_table_uploads = field['sub_fields'].select { |ss| ss['type'] == 'upload' } -- not available yet
|
90
|
+
field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
|
91
|
+
if field_table_molecules.present?
|
92
|
+
col_ids = field_table_molecules.map { |x| x.values[0] }
|
93
|
+
col_ids.each do |col_id|
|
94
|
+
field['sub_values'].each do |sub_value|
|
95
|
+
next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
|
96
|
+
|
97
|
+
svalue = sub_value[col_id]['value']
|
98
|
+
next unless svalue['el_id'].present? && svalue['el_inchikey'].present?
|
99
|
+
|
100
|
+
tmol = Molecule.find_by(id: svalue['el_id'])
|
101
|
+
sub_value[col_id]['value']['el_id'] = fetch_one.call(tmol) unless tmol.nil?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
instance.properties = properties
|
109
|
+
[instance, attachments]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|