labimotion 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/lib/labimotion/api.rb +19 -0
  3. data/lib/labimotion/apis/converter_api.rb +68 -0
  4. data/lib/labimotion/apis/generic_dataset_api.rb +50 -0
  5. data/lib/labimotion/apis/generic_element_api.rb +339 -0
  6. data/lib/labimotion/apis/labimotion_hub_api.rb +53 -0
  7. data/lib/labimotion/apis/segment_api.rb +144 -0
  8. data/lib/labimotion/entities/application_entity.rb +88 -0
  9. data/lib/labimotion/entities/dataset_entity.rb +16 -0
  10. data/lib/labimotion/entities/dataset_klass_entity.rb +9 -0
  11. data/lib/labimotion/entities/element_entity.rb +108 -0
  12. data/lib/labimotion/entities/element_klass_entity.rb +10 -0
  13. data/lib/labimotion/entities/element_revision_entity.rb +57 -0
  14. data/lib/labimotion/entities/eln_element_entity.rb +110 -0
  15. data/lib/labimotion/entities/generic_entity.rb +54 -0
  16. data/lib/labimotion/entities/generic_klass_entity.rb +14 -0
  17. data/lib/labimotion/entities/generic_public_entity.rb +25 -0
  18. data/lib/labimotion/entities/klass_revision_entity.rb +20 -0
  19. data/lib/labimotion/entities/segment_entity.rb +62 -0
  20. data/lib/labimotion/entities/segment_klass_entity.rb +8 -0
  21. data/lib/labimotion/entities/segment_revision_entity.rb +55 -0
  22. data/lib/labimotion/helpers/converter_helpers.rb +13 -0
  23. data/lib/labimotion/helpers/dataset_helpers.rb +38 -0
  24. data/lib/labimotion/helpers/element_helpers.rb +268 -0
  25. data/lib/labimotion/helpers/generic_helpers.rb +252 -0
  26. data/lib/labimotion/helpers/repository_helpers.rb +14 -0
  27. data/lib/labimotion/helpers/sample_association_helpers.rb +126 -0
  28. data/lib/labimotion/helpers/search_helpers.rb +62 -0
  29. data/lib/labimotion/helpers/segment_helpers.rb +97 -0
  30. data/lib/labimotion/libs/converter.rb +325 -0
  31. data/lib/labimotion/libs/export_dataset.rb +121 -0
  32. data/lib/labimotion/libs/nmr_mapper.rb +265 -0
  33. data/lib/labimotion/libs/nmr_mapper_repo.rb +263 -0
  34. data/lib/labimotion/libs/template_hub.rb +55 -0
  35. data/lib/labimotion/models/collections_element.rb +42 -0
  36. data/lib/labimotion/models/concerns/attachment_converter.rb +42 -0
  37. data/lib/labimotion/models/concerns/datasetable.rb +50 -0
  38. data/lib/labimotion/models/concerns/generic_klass_revisions.rb +39 -0
  39. data/lib/labimotion/models/concerns/generic_revisions.rb +43 -0
  40. data/lib/labimotion/models/concerns/segmentable.rb +74 -0
  41. data/lib/labimotion/models/dataset.rb +14 -0
  42. data/lib/labimotion/models/dataset_klass.rb +25 -0
  43. data/lib/labimotion/models/dataset_klasses_revision.rb +9 -0
  44. data/lib/labimotion/models/datasets_revision.rb +9 -0
  45. data/lib/labimotion/models/element.rb +121 -0
  46. data/lib/labimotion/models/element_klass.rb +25 -0
  47. data/lib/labimotion/models/element_klasses_revision.rb +9 -0
  48. data/lib/labimotion/models/elements_element.rb +11 -0
  49. data/lib/labimotion/models/elements_revision.rb +8 -0
  50. data/lib/labimotion/models/elements_sample.rb +11 -0
  51. data/lib/labimotion/models/segment.rb +14 -0
  52. data/lib/labimotion/models/segment_klass.rb +24 -0
  53. data/lib/labimotion/models/segment_klasses_revision.rb +9 -0
  54. data/lib/labimotion/models/segments_revision.rb +9 -0
  55. data/lib/labimotion/utils/con_state.rb +13 -0
  56. data/lib/labimotion/utils/export.rb +112 -0
  57. data/lib/labimotion/utils/import.rb +186 -0
  58. data/lib/labimotion/utils/search.rb +112 -0
  59. data/lib/labimotion/utils/serializer.rb +78 -0
  60. data/lib/labimotion/version.rb +6 -0
  61. data/lib/labimotion.rb +95 -0
  62. metadata +119 -0
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ module Labimotion
4
+ ## ApplicationEntity
5
+ class ApplicationEntity < Grape::Entity
6
+ CUSTOM_ENTITY_OPTIONS = %i[anonymize_below anonymize_with].freeze
7
+
8
+ format_with(:eln_timestamp) do |datetime|
9
+ datetime.present? ? datetime&.strftime('%Y-%m-%d %H:%M:%S %Z') : nil
10
+ end
11
+
12
+ def self.expose!(*args)
13
+ fields = args.first
14
+ options = args.last.is_a?(Hash) ? args.pop : {}
15
+ options = merge_options(options) # merges additional params set in #with_options
16
+ expose_fields_with_anonymization!(fields, options)
17
+ end
18
+
19
+ # rubocop:disable Metrics/MethodLength
20
+ def self.expose_fields_with_anonymization!(fields, options)
21
+ anonymize_below = options[:anonymize_below] || 0
22
+ anonymize_with = options.key?(:anonymize_with) ? options[:anonymize_with] : '***'
23
+
24
+ Array(fields).each do |field|
25
+ expose(field, options) do |represented_object, _options|
26
+ if detail_levels[represented_object.class] < anonymize_below
27
+ anonymize_with
28
+ elsif respond_to?(field, true) # Entity has a method with the same name
29
+ send(field)
30
+ elsif represented_object.respond_to?(field)
31
+ represented_object.public_send(field)
32
+ else
33
+ represented_object[field] # works both for AR and Hash objects
34
+ end
35
+ end
36
+ end
37
+ end
38
+ private_class_method :expose_fields_with_anonymization!
39
+ # rubocop:enable Metrics/MethodLength
40
+
41
+ def self.expose_timestamps(timestamp_fields: %i[created_at updated_at], **additional_args)
42
+ timestamp_fields.each do |field|
43
+ expose field, format_with: :eln_timestamp, **additional_args
44
+ end
45
+ end
46
+
47
+ # overridden method from Grape::Entity to support our custom anonymization options
48
+ # https://github.com/ruby-grape/grape-entity/blob/v0.7.1/lib/grape_entity/entity.rb#L565
49
+ def self.valid_options(options)
50
+ options.each_key do |key|
51
+ next if OPTIONS.include?(key) || CUSTOM_ENTITY_OPTIONS.include?(key)
52
+
53
+ raise ArgumentError, "#{key.inspect} is not a valid option."
54
+ end
55
+
56
+ options[:using] = options.delete(:with) if options.key?(:with)
57
+ options
58
+ end
59
+ private_class_method :valid_options
60
+
61
+ private
62
+
63
+ def displayed_in_list?
64
+ options[:displayed_in_list] == true
65
+ end
66
+
67
+ def current_user
68
+ unless options[:current_user]
69
+ raise MissingCurrentUserError, "#{self.class} requires a current user to work properly"
70
+ end
71
+
72
+ options[:current_user]
73
+ end
74
+
75
+ def detail_levels
76
+ maximal_default_levels = Hash.new(10) # every requested detail level will be returned as 10
77
+ minimal_default_levels = Hash.new(0) # every requested detail level will be returned as 0
78
+ return maximal_default_levels if !options.key?(:detail_levels) || options[:detail_levels].empty?
79
+
80
+ # When explicitly configured detail levels are available, we want to return only those and all other
81
+ # requests (by using `detail_levels[SomeUnconfiguredModel]`) should return the minimum detail level
82
+ minimal_default_levels.merge(options[:detail_levels])
83
+ end
84
+
85
+ class MissingCurrentUserError < StandardError
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ require 'labimotion/entities/application_entity'
4
+ module Labimotion
5
+ # Dataset entity
6
+ class DatasetEntity < ApplicationEntity
7
+ expose :id, :dataset_klass_id, :properties, :properties_release, :element_id, :element_type, :klass_ols, :klass_label, :klass_uuid
8
+ def klass_ols
9
+ object&.dataset_klass&.ols_term_id
10
+ end
11
+
12
+ def klass_label
13
+ object&.dataset_klass&.label
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ require 'labimotion/entities/generic_klass_entity'
3
+ module Labimotion
4
+ class DatasetKlassEntity < GenericKlassEntity
5
+ expose(
6
+ :ols_term_id,
7
+ )
8
+ end
9
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/entities/application_entity'
4
+ ## TODO: Refactor labimotion to use the same entities as chemotion
5
+ module Labimotion
6
+ class ElementEntity < ApplicationEntity
7
+ with_options(anonymize_below: 0) do
8
+ expose! :can_copy
9
+ expose! :container, using: 'Entities::ContainerEntity'
10
+ expose! :created_by
11
+ expose! :id
12
+ expose! :is_restricted
13
+ expose! :klass_uuid
14
+ expose! :name
15
+ expose! :properties
16
+ expose! :properties_release
17
+ expose! :short_label
18
+ expose! :type
19
+ expose! :uuid
20
+ end
21
+
22
+ with_options(anonymize_below: 10) do
23
+ expose! :element_klass, anonymize_with: nil, using: 'Labimotion::ElementKlassEntity'
24
+ expose! :segments, anonymize_with: [], using: 'Labimotion::SegmentEntity'
25
+ expose! :tag, anonymize_with: nil, using: 'Entities::ElementTagEntity'
26
+ end
27
+
28
+ expose_timestamps
29
+
30
+
31
+ private
32
+
33
+ def is_restricted
34
+ detail_levels[Labimotion::Element] < 10
35
+ end
36
+
37
+ # TODO: Refactor this method to something more readable/understandable
38
+ def properties
39
+ (object.properties['layers']&.keys || []).each do |key|
40
+ # layer = object.properties[key]
41
+ field_sample_molecules = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'drag_sample' || ss['type'] == 'drag_molecule' }
42
+ field_sample_molecules.each do |field|
43
+ idx = object.properties['layers'][key]['fields'].index(field)
44
+ sid = field.dig('value', 'el_id')
45
+ next unless sid.present?
46
+
47
+ el = field['type'] == 'drag_sample' ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
48
+ next unless el.present?
49
+ next unless object.properties.dig('layers', key, 'fields', idx, 'value').present?
50
+
51
+ object.properties['layers'][key]['fields'][idx]['value']['el_label'] = el.short_label if field['type'] == 'drag_sample'
52
+ object.properties['layers'][key]['fields'][idx]['value']['el_tip'] = el.short_label if field['type'] == 'drag_sample'
53
+ object.properties['layers'][key]['fields'][idx]['value']['el_svg'] = field['type'] == 'drag_sample' ? el.get_svg_path : File.join('/images', 'molecules', el.molecule_svg_file)
54
+ end
55
+
56
+ field_tables = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
57
+ field_tables.each do |field|
58
+ idx = object.properties['layers'][key]['fields'].index(field)
59
+ next unless field['sub_values'].present? && field['sub_fields'].present?
60
+
61
+ field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
62
+ object.properties['layers'][key]['fields'][idx] = set_table(field, field_table_molecules, 'Molecule') if field_table_molecules.present?
63
+
64
+ field_table_samples = field['sub_fields'].select { |ss| ss['type'] == 'drag_sample' }
65
+ object.properties['layers'][key]['fields'][idx] = set_table(field, field_table_samples, 'Sample') if field_table_samples.present?
66
+ end
67
+ end
68
+ object.properties
69
+ end
70
+
71
+ def type
72
+ object.element_klass.name # 'genericEl' #object.type
73
+ end
74
+
75
+ def set_table(field, field_table_objs, obj)
76
+ col_ids = field_table_objs.map { |x| x.values[0] }
77
+ col_ids.each do |col_id|
78
+ field['sub_values'].each do |sub_value|
79
+ next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
80
+
81
+ find_obj = obj.constantize.find_by(id: sub_value[col_id]['value']['el_id'])
82
+ next unless find_obj.present?
83
+
84
+ case obj
85
+ when 'Molecule'
86
+ sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_obj.molecule_svg_file)
87
+ sub_value[col_id]['value']['el_inchikey'] = find_obj.inchikey
88
+ sub_value[col_id]['value']['el_smiles'] = find_obj.cano_smiles
89
+ sub_value[col_id]['value']['el_iupac'] = find_obj.iupac_name
90
+ sub_value[col_id]['value']['el_molecular_weight'] = find_obj.molecular_weight
91
+ when 'Sample'
92
+ sub_value[col_id]['value']['el_svg'] = find_obj.get_svg_path
93
+ sub_value[col_id]['value']['el_label'] = find_obj.short_label
94
+ sub_value[col_id]['value']['el_short_label'] = find_obj.short_label
95
+ sub_value[col_id]['value']['el_name'] = find_obj.name
96
+ sub_value[col_id]['value']['el_external_label'] = find_obj.external_label
97
+ sub_value[col_id]['value']['el_molecular_weight'] = find_obj.decoupled ? find_obj.molecular_mass : find_obj.molecule.molecular_weight
98
+ end
99
+ end
100
+ end
101
+ field
102
+ end
103
+
104
+ def can_copy
105
+ true
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ require 'labimotion/entities/generic_klass_entity'
4
+
5
+ module Labimotion
6
+ # ElementKlassEntity
7
+ class ElementKlassEntity < GenericKlassEntity
8
+ expose :name, :icon_name, :klass_prefix, :is_generic
9
+ end
10
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/entities/application_entity'
4
+ module Labimotion
5
+ # ElementRevisionEntity
6
+ class ElementRevisionEntity < ApplicationEntity
7
+ expose :id, :element_id, :uuid, :name, :klass_uuid, :properties, :created_at
8
+ def created_at
9
+ object.created_at.strftime('%d.%m.%Y, %H:%M')
10
+ end
11
+
12
+ def properties
13
+ object.properties['layers']&.keys.each do |key|
14
+ field_sample_molecules = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'drag_sample' || ss['type'] == 'drag_molecule' }
15
+ field_sample_molecules.each do |field|
16
+ idx = object.properties['layers'][key]['fields'].index(field)
17
+ sid = field.dig('value', 'el_id')
18
+ next unless sid.present?
19
+
20
+ el = field['type'] == 'drag_sample' ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
21
+ next unless el.present?
22
+ next unless object.properties.dig('layers', key, 'fields', idx, 'value').present?
23
+
24
+ object.properties['layers'][key]['fields'][idx]['value']['el_label'] = el.short_label if field['type'] == 'drag_sample'
25
+ object.properties['layers'][key]['fields'][idx]['value']['el_tip'] = el.short_label if field['type'] == 'drag_sample'
26
+ object.properties['layers'][key]['fields'][idx]['value']['el_svg'] = field['type'] == 'drag_sample' ? el.get_svg_path : File.join('/images', 'molecules', el.molecule_svg_file)
27
+ end
28
+
29
+ field_tables = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
30
+ field_tables.each do |field|
31
+ next unless field['sub_values'].present? && field['sub_fields'].present?
32
+
33
+ field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
34
+ next unless field_table_molecules.present?
35
+
36
+ col_ids = field_table_molecules.map { |x| x.values[0] }
37
+ col_ids.each do |col_id|
38
+ field_table_values = field['sub_values'].each do |sub_value|
39
+ next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
40
+
41
+ find_mol = Molecule.find_by(id: sub_value[col_id]['value']['el_id'])
42
+ next unless find_mol.present?
43
+
44
+ sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_mol.molecule_svg_file)
45
+ sub_value[col_id]['value']['el_inchikey'] = find_mol.inchikey
46
+ sub_value[col_id]['value']['el_smiles'] = find_mol.cano_smiles
47
+ sub_value[col_id]['value']['el_iupac'] = find_mol.iupac_name
48
+ sub_value[col_id]['value']['el_molecular_weight'] = find_mol.molecular_weight
49
+ end
50
+ end
51
+ end
52
+ end
53
+ object.properties['select_options'] = object.properties_release['select_options']
54
+ object.properties
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ require 'labimotion/entities/application_entity'
4
+ module Labimotion
5
+ ## ElementEntity
6
+ class ElnElementEntity < ApplicationEntity
7
+ with_options(anonymize_below: 0) do
8
+ expose! :created_by
9
+ expose! :id
10
+ expose! :is_restricted
11
+ expose! :klass_uuid
12
+ expose! :name
13
+ expose! :properties
14
+ expose! :properties_release
15
+ expose! :short_label
16
+ expose! :type
17
+ expose! :uuid
18
+ end
19
+
20
+ expose(
21
+ :can_copy, unless: ->(_instance, _options) { displayed_in_list? }
22
+ )
23
+
24
+ private
25
+
26
+ def properties
27
+ (object.properties['layers']&.keys || []).each do |key|
28
+ # layer = object.properties[key]
29
+ field_sample_molecules = object.properties['layers'][key]['fields'].select do |ss|
30
+ ss['type'] == 'drag_sample' || ss['type'] == 'drag_molecule'
31
+ end
32
+ field_sample_molecules.each do |field|
33
+ idx = object.properties['layers'][key]['fields'].index(field)
34
+ sid = field.dig('value', 'el_id')
35
+ next unless sid.present?
36
+
37
+ el = field['type'] == 'drag_sample' ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
38
+ next unless el.present?
39
+ next unless object.properties.dig('layers', key, 'fields', idx, 'value').present?
40
+
41
+ if field['type'] == 'drag_sample'
42
+ object.properties['layers'][key]['fields'][idx]['value']['el_label'] =
43
+ el.short_label
44
+ end
45
+ if field['type'] == 'drag_sample'
46
+ object.properties['layers'][key]['fields'][idx]['value']['el_tip'] =
47
+ el.short_label
48
+ end
49
+ object.properties['layers'][key]['fields'][idx]['value']['el_svg'] =
50
+ field['type'] == 'drag_sample' ? el.get_svg_path : File.join('/images', 'molecules', el.molecule_svg_file)
51
+ end
52
+
53
+ field_tables = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
54
+ field_tables.each do |field|
55
+ idx = object.properties['layers'][key]['fields'].index(field)
56
+ next unless field['sub_values'].present? && field['sub_fields'].present?
57
+
58
+ field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
59
+ if field_table_molecules.present?
60
+ object.properties['layers'][key]['fields'][idx] =
61
+ set_table(field, field_table_molecules, 'Molecule')
62
+ end
63
+
64
+ field_table_samples = field['sub_fields'].select { |ss| ss['type'] == 'drag_sample' }
65
+ if field_table_samples.present?
66
+ object.properties['layers'][key]['fields'][idx] =
67
+ set_table(field, field_table_samples, 'Sample')
68
+ end
69
+ end
70
+ end
71
+ object.properties
72
+ end
73
+
74
+ def type
75
+ object.element_klass.name
76
+ end
77
+
78
+ def set_table(field, field_table_objs, obj)
79
+ col_ids = field_table_objs.map { |x| x.values[0] }
80
+ col_ids.each do |col_id|
81
+ field['sub_values'].each do |sub_value|
82
+ unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
83
+ next
84
+ end
85
+
86
+ find_obj = obj.constantize.find_by(id: sub_value[col_id]['value']['el_id'])
87
+ next unless find_obj.present?
88
+
89
+ case obj
90
+ when 'Molecule'
91
+ sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_obj.molecule_svg_file)
92
+ sub_value[col_id]['value']['el_inchikey'] = find_obj.inchikey
93
+ sub_value[col_id]['value']['el_smiles'] = find_obj.cano_smiles
94
+ sub_value[col_id]['value']['el_iupac'] = find_obj.iupac_name
95
+ sub_value[col_id]['value']['el_molecular_weight'] = find_obj.molecular_weight
96
+ when 'Sample'
97
+ sub_value[col_id]['value']['el_svg'] = find_obj.get_svg_path
98
+ sub_value[col_id]['value']['el_label'] = find_obj.short_label
99
+ sub_value[col_id]['value']['el_short_label'] = find_obj.short_label
100
+ sub_value[col_id]['value']['el_name'] = find_obj.name
101
+ sub_value[col_id]['value']['el_external_label'] = find_obj.external_label
102
+ sub_value[col_id]['value']['el_molecular_weight'] =
103
+ find_obj.decoupled ? find_obj.molecular_mass : find_obj.molecule.molecular_weight
104
+ end
105
+ end
106
+ end
107
+ field
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/entities/application_entity'
4
+
5
+ # Entity module
6
+ module Labimotion
7
+ class GenericEntity < Labimotion::ApplicationEntity
8
+ expose :id, :is_active, :label, :desc, :place, :released_at
9
+
10
+ expose :element_klass_id do |obj|
11
+ obj[:element_klass_id] || 0
12
+ end
13
+
14
+ expose :klass_name do |obj|
15
+ obj[:name] || ''
16
+ end
17
+
18
+ expose :ols_term_id do |obj|
19
+ obj[:ols_term_id] || ''
20
+ end
21
+
22
+ expose :icon_name do |obj|
23
+ obj[:icon_name] || ''
24
+ end
25
+
26
+ expose :klass_prefix do |obj|
27
+ obj[:klass_prefix] || ''
28
+ end
29
+
30
+ expose :is_generic do |obj|
31
+ obj[:is_generic] || true
32
+ end
33
+
34
+ expose :uuid do |obj|
35
+ obj[:uuid] || ''
36
+ end
37
+
38
+ expose :properties_release do |obj|
39
+ obj[:properties_release] || {}
40
+ end
41
+
42
+ expose :element_klass do |obj|
43
+ if obj[:element_klass_id]
44
+ Labimotion::GenericEntity.represent(obj.element_klass)
45
+ else
46
+ {}
47
+ end
48
+ end
49
+
50
+ expose :identifier do |obj|
51
+ obj[:identifier] || ''
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ require 'labimotion/entities/application_entity'
4
+ module Labimotion
5
+ # GenericKlassEntity
6
+ class GenericKlassEntity < ApplicationEntity
7
+ expose :id, :uuid, :label, :desc, :properties_template, :properties_release, :is_active,
8
+ :place, :released_at, :identifier, :sync_time, :created_by, :updated_by, :created_at, :updated_at
9
+ expose_timestamps(timestamp_fields: [:released_at])
10
+ expose_timestamps(timestamp_fields: [:created_at])
11
+ expose_timestamps(timestamp_fields: [:updated_at])
12
+ expose_timestamps(timestamp_fields: [:sync_time])
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/entities/application_entity'
4
+
5
+ # Entity module
6
+ module Labimotion
7
+ class GenericPublicEntity < Labimotion::ApplicationEntity
8
+ expose! :name
9
+ expose! :desc
10
+ expose! :icon_name
11
+ expose! :klass_prefix
12
+ expose! :klass_name
13
+ expose! :label
14
+ expose! :identifier
15
+ expose! :released_at
16
+ expose! :properties_release, if: :displayed
17
+ expose :element_klass do |obj|
18
+ if obj[:element_klass_id]
19
+ { :label => obj.element_klass.label, :icon_name => obj.element_klass.icon_name }
20
+ else
21
+ {}
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ # KlassRevisionEntity
5
+ class KlassRevisionEntity < ApplicationEntity
6
+ expose :id, :uuid, :properties_release, :released_at
7
+
8
+ expose :klass_id do |object|
9
+ klass_id = object.element_klass_id if object.respond_to? :element_klass_id
10
+ klass_id = object.segment_klass_id if object.respond_to? :segment_klass_id
11
+ klass_id = object.dataset_klass_id if object.respond_to? :dataset_klass_id
12
+ klass_id
13
+ end
14
+
15
+ def released_at
16
+ object.released_at&.strftime('%d.%m.%Y, %H:%M')
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/entities/application_entity'
4
+ module Labimotion
5
+ ## Segment entity
6
+ class SegmentEntity < ApplicationEntity
7
+ expose :id, :segment_klass_id, :element_type, :element_id, :properties, :properties_release, :uuid, :klass_uuid, :klass_label
8
+
9
+ def klass_label
10
+ object.segment_klass.label
11
+ end
12
+
13
+ def properties # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength
14
+ return unless object.respond_to?(:properties)
15
+
16
+ return if object&.properties.dig('layers').blank?
17
+
18
+ object&.properties['layers'].each_key do |key| # rubocop:disable Metrics/BlockLength
19
+ next if object&.properties.dig('layers', key, 'fields').blank?
20
+
21
+ field_sample_molecules = object&.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'drag_molecule' }
22
+ field_sample_molecules.each do |field|
23
+ idx = object&.properties['layers'][key]['fields'].index(field)
24
+ sid = field.dig('value', 'el_id')
25
+ next if sid.blank?
26
+
27
+ el = Molecule.find_by(id: sid)
28
+ next if el.blank?
29
+
30
+ next if object&.properties.dig('layers', key, 'fields', idx, 'value').blank?
31
+
32
+ object&.properties['layers'][key]['fields'][idx]['value']['el_svg'] = File.join('/images', 'molecules', el.molecule_svg_file)
33
+ end
34
+
35
+ field_tables = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
36
+ field_tables.each do |field|
37
+ next unless field['sub_values'].present? && field['sub_fields'].present?
38
+
39
+ field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
40
+ next if field_table_molecules.blank?
41
+
42
+ col_ids = field_table_molecules.map { |x| x.values[0] }
43
+ col_ids.each do |col_id|
44
+ field['sub_values'].each do |sub_value|
45
+ next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
46
+
47
+ find_mol = Molecule.find_by(id: sub_value[col_id]['value']['el_id'])
48
+ next if find_mol.blank?
49
+
50
+ sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_mol.molecule_svg_file)
51
+ sub_value[col_id]['value']['el_inchikey'] = find_mol.inchikey
52
+ sub_value[col_id]['value']['el_smiles'] = find_mol.cano_smiles
53
+ sub_value[col_id]['value']['el_iupac'] = find_mol.iupac_name
54
+ sub_value[col_id]['value']['el_molecular_weight'] = find_mol.molecular_weight
55
+ end
56
+ end
57
+ end
58
+ end
59
+ object&.properties
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'labimotion/entities/generic_klass_entity'
3
+ require 'labimotion/entities/element_klass_entity'
4
+ module Labimotion
5
+ class SegmentKlassEntity < Labimotion::GenericKlassEntity
6
+ expose :element_klass, using: Labimotion::ElementKlassEntity
7
+ end
8
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ require 'labimotion/entities/application_entity'
4
+ module Labimotion
5
+ class SegmentRevisionEntity < ApplicationEntity
6
+ expose :id, :segment_id, :uuid, :klass_uuid, :properties, :created_at
7
+ def created_at
8
+ object.created_at.strftime('%d.%m.%Y, %H:%M')
9
+ end
10
+
11
+ def properties
12
+ object.properties['layers']&.keys.each do |key|
13
+ field_sample_molecules = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'drag_sample' || ss['type'] == 'drag_molecule' }
14
+ field_sample_molecules.each do |field|
15
+ idx = object.properties['layers'][key]['fields'].index(field)
16
+ sid = field.dig('value', 'el_id')
17
+ next unless sid.present?
18
+
19
+ el = field['type'] == 'drag_sample' ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
20
+ next unless el.present?
21
+ next unless object.properties.dig('layers', key, 'fields', idx, 'value').present?
22
+
23
+ object.properties['layers'][key]['fields'][idx]['value']['el_label'] = el.short_label if field['type'] == 'drag_sample'
24
+ object.properties['layers'][key]['fields'][idx]['value']['el_tip'] = el.short_label if field['type'] == 'drag_sample'
25
+ object.properties['layers'][key]['fields'][idx]['value']['el_svg'] = field['type'] == 'drag_sample' ? el.get_svg_path : File.join('/images', 'molecules', el.molecule_svg_file)
26
+ end
27
+
28
+ field_tables = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
29
+ field_tables.each do |field|
30
+ next unless field['sub_values'].present? && field['sub_fields'].present?
31
+
32
+ field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
33
+ next unless field_table_molecules.present?
34
+
35
+ col_ids = field_table_molecules.map { |x| x.values[0] }
36
+ col_ids.each do |col_id|
37
+ field_table_values = field['sub_values'].each do |sub_value|
38
+ next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
39
+
40
+ find_mol = Molecule.find_by(id: sub_value[col_id]['value']['el_id'])
41
+ next unless find_mol.present?
42
+
43
+ sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_mol.molecule_svg_file)
44
+ sub_value[col_id]['value']['el_inchikey'] = find_mol.inchikey
45
+ sub_value[col_id]['value']['el_smiles'] = find_mol.cano_smiles
46
+ sub_value[col_id]['value']['el_iupac'] = find_mol.iupac_name
47
+ sub_value[col_id]['value']['el_molecular_weight'] = find_mol.molecular_weight
48
+ end
49
+ end
50
+ end
51
+ end
52
+ object.properties
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ require 'grape'
3
+
4
+ module Labimotion
5
+ ## ElementHelpers
6
+ module ConverterHelpers
7
+ extend Grape::API::Helpers
8
+
9
+ def demo(params)
10
+ ### TODO: implement demo
11
+ end
12
+ end
13
+ end