labimotion 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|