labimotion 1.0.18 → 1.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb5fd5761e888bf207676bbf97543cf5636dec7ab38fb70ee1d9481bc2fce073
4
- data.tar.gz: 99c3efcefccd2c5ac2460c2c1e5b31b4f3aa3740f95511efa9453f04f2218deb
3
+ metadata.gz: 0c374697be6dd59785865b85ea34a92de6d9e87d8d0fe9d5416b5b58c5f18f11
4
+ data.tar.gz: 11b8842141477f92d08e50c0fc55c29f82c7a098dc8c08ed9be610b9d037c0ae
5
5
  SHA512:
6
- metadata.gz: 39cd347d558a49e57931c2d818530ea9cce85ea01e1a8950d04977cbe6794e3f777ec551bb37af058ca773083301a1bbd79d57d85733c882068d081a5d8b527d
7
- data.tar.gz: 19c0ededc605def31634b210e0117411841afaad5c7b84dc9f57a96cfcab6177b54d11f5bf70bb0f70752589aebe37d0ed5f53a22bbaa486002a66d2830a3210
6
+ metadata.gz: 0ebbb6edd334c5f13bbf3196cc7f5b56510019925f516abb35404b0943c9546e21fd16227ffebe5365955d9202b7201b795fac019c72050d0a59f902d4aa70ca
7
+ data.tar.gz: eded51a9e589660b0a6dcf20187eb715e946448fa9a047263176212c0136d0a648c9015d50a3de0ae06ea39ba6942fcfc23e00b085aecaa583e8faa57e67f1ee
@@ -310,7 +310,10 @@ module Labimotion
310
310
  end
311
311
  route_param :id do
312
312
  before do
313
- error!('401 Unauthorized', 401) unless current_user.matrix_check_by_name('genericElement') && ElementPolicy.new(current_user, Element.find(params[:id])).read?
313
+ @element_policy = ElementPolicy.new(current_user, Element.find(params[:id]))
314
+ error!('401 Unauthorized', 401) unless current_user.matrix_check_by_name('genericElement') && @element_policy.read?
315
+ rescue ActiveRecord::RecordNotFound
316
+ error!('404 Not Found', 404)
314
317
  end
315
318
 
316
319
  get do
@@ -321,10 +324,12 @@ module Labimotion
321
324
  attachments: attach_thumbnail(element&.attachments)
322
325
  }
323
326
  else
327
+ #byebug
324
328
  {
325
329
  element: Labimotion::ElementEntity.represent(
326
330
  element,
327
331
  detail_levels: ElementDetailLevelCalculator.new(user: current_user, element: element).detail_levels,
332
+ policy: @element_policy
328
333
  ),
329
334
  attachments: attach_thumbnail(element&.attachments)
330
335
  }
@@ -19,7 +19,7 @@ module Labimotion
19
19
  get do
20
20
  list = "Labimotion::#{params[:klass]}".constantize.where(is_active: true).where.not(released_at: nil)
21
21
  list = list.where(is_generic: true) if params[:klass] == 'ElementKlass'
22
- entities = Labimotion::GenericPublicEntity.represent(list, displayed: params[:with_props])
22
+ entities = Labimotion::GenericPublicEntity.represent(list, displayed: params[:with_props], root: 'list')
23
23
  rescue StandardError => e
24
24
  Labimotion.log_exception(e, current_user)
25
25
  []
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'labimotion/entities/application_entity'
3
+ require 'labimotion/entities/properties_entity'
4
4
  ## TODO: Refactor labimotion to use the same entities as chemotion
5
5
  module Labimotion
6
- class ElementEntity < ApplicationEntity
6
+ class ElementEntity < PropertiesEntity
7
7
  with_options(anonymize_below: 0) do
8
- expose! :can_copy
8
+ expose! :can_copy, unless: :displayed_in_list
9
+ expose! :can_publish, unless: :displayed_in_list
10
+ expose! :can_update, unless: :displayed_in_list
9
11
  expose! :container, using: 'Entities::ContainerEntity'
10
12
  expose! :created_by
11
13
  expose! :id
@@ -35,75 +37,21 @@ module Labimotion
35
37
  detail_levels[Labimotion::Element] < 10
36
38
  end
37
39
 
38
- # TODO: Refactor this method to something more readable/understandable
39
- def properties
40
- (object.properties['layers']&.keys || []).each do |key|
41
- # layer = object.properties[key]
42
- field_sample_molecules = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'drag_sample' || ss['type'] == 'drag_molecule' }
43
- field_sample_molecules.each do |field|
44
- idx = object.properties['layers'][key]['fields'].index(field)
45
- sid = field.dig('value', 'el_id')
46
- next unless sid.present?
47
-
48
- el = field['type'] == 'drag_sample' ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
49
- next unless el.present?
50
- next unless object.properties.dig('layers', key, 'fields', idx, 'value').present?
51
-
52
- object.properties['layers'][key]['fields'][idx]['value']['el_label'] = el.short_label if field['type'] == 'drag_sample'
53
- object.properties['layers'][key]['fields'][idx]['value']['el_tip'] = el.short_label if field['type'] == 'drag_sample'
54
- 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)
55
- end
56
-
57
- field_tables = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
58
- field_tables.each do |field|
59
- idx = object.properties['layers'][key]['fields'].index(field)
60
- next unless field['sub_values'].present? && field['sub_fields'].present?
61
-
62
- field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
63
- object.properties['layers'][key]['fields'][idx] = set_table(field, field_table_molecules, 'Molecule') if field_table_molecules.present?
64
-
65
- field_table_samples = field['sub_fields'].select { |ss| ss['type'] == 'drag_sample' }
66
- object.properties['layers'][key]['fields'][idx] = set_table(field, field_table_samples, 'Sample') if field_table_samples.present?
67
- end
68
- end
69
- object.properties
70
- end
71
-
72
40
  def type
73
41
  object.element_klass.name # 'genericEl' #object.type
74
42
  end
75
43
 
76
- def set_table(field, field_table_objs, obj)
77
- col_ids = field_table_objs.map { |x| x.values[0] }
78
- col_ids.each do |col_id|
79
- field['sub_values'].each do |sub_value|
80
- next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
81
-
82
- find_obj = obj.constantize.find_by(id: sub_value[col_id]['value']['el_id'])
83
- next unless find_obj.present?
84
-
85
- case obj
86
- when 'Molecule'
87
- sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_obj.molecule_svg_file)
88
- sub_value[col_id]['value']['el_inchikey'] = find_obj.inchikey
89
- sub_value[col_id]['value']['el_smiles'] = find_obj.cano_smiles
90
- sub_value[col_id]['value']['el_iupac'] = find_obj.iupac_name
91
- sub_value[col_id]['value']['el_molecular_weight'] = find_obj.molecular_weight
92
- when 'Sample'
93
- sub_value[col_id]['value']['el_svg'] = find_obj.get_svg_path
94
- sub_value[col_id]['value']['el_label'] = find_obj.short_label
95
- sub_value[col_id]['value']['el_short_label'] = find_obj.short_label
96
- sub_value[col_id]['value']['el_name'] = find_obj.name
97
- sub_value[col_id]['value']['el_external_label'] = find_obj.external_label
98
- sub_value[col_id]['value']['el_molecular_weight'] = find_obj.decoupled ? find_obj.molecular_mass : find_obj.molecule.molecular_weight
99
- end
100
- end
101
- end
102
- field
44
+ def can_update
45
+ self.options[:policy].try(:update?) || false
103
46
  end
104
47
 
105
48
  def can_copy
106
- true
49
+ self.options[:policy].try(:copy?) || false
107
50
  end
51
+
52
+ def can_publish
53
+ self.options[:policy].try(:destroy?) || false
54
+ end
55
+
108
56
  end
109
57
  end
@@ -0,0 +1,72 @@
1
+ require 'labimotion/entities/application_entity'
2
+
3
+ # Entity module
4
+ module Labimotion
5
+ class PropertiesEntity < Labimotion::ApplicationEntity
6
+
7
+ # TODO: Refactor this method to something more readable/understandable
8
+ def properties
9
+ (object&.properties.is_a?(Hash) && object.properties['layers']&.keys || []).each do |key|
10
+ # layer = object.properties[key]
11
+ field_sample_molecules = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'drag_sample' || ss['type'] == 'drag_molecule' }
12
+ field_sample_molecules.each do |field|
13
+ idx = object.properties['layers'][key]['fields'].index(field)
14
+ sid = field.dig('value', 'el_id')
15
+ next unless sid.present?
16
+
17
+ el = field['type'] == 'drag_sample' ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
18
+ next unless el.present?
19
+ next unless object.properties.dig('layers', key, 'fields', idx, 'value').present?
20
+
21
+ object.properties['layers'][key]['fields'][idx]['value']['el_label'] = el.short_label if field['type'] == 'drag_sample'
22
+ object.properties['layers'][key]['fields'][idx]['value']['el_tip'] = el.short_label if field['type'] == 'drag_sample'
23
+ 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)
24
+ end
25
+
26
+ field_tables = object.properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
27
+ field_tables.each do |field|
28
+ idx = object.properties['layers'][key]['fields'].index(field)
29
+ next unless field['sub_values'].present? && field['sub_fields'].present?
30
+
31
+ field_table_molecules = field['sub_fields'].select { |ss| ss['type'] == 'drag_molecule' }
32
+ object.properties['layers'][key]['fields'][idx] = set_table(field, field_table_molecules, 'Molecule') if field_table_molecules.present?
33
+
34
+ field_table_samples = field['sub_fields'].select { |ss| ss['type'] == 'drag_sample' }
35
+ object.properties['layers'][key]['fields'][idx] = set_table(field, field_table_samples, 'Sample') if field_table_samples.present?
36
+ end
37
+ end
38
+ object.properties
39
+ end
40
+
41
+
42
+ def set_table(field, field_table_objs, obj)
43
+ col_ids = field_table_objs.map { |x| x.values[0] }
44
+ col_ids.each do |col_id|
45
+ field['sub_values'].each do |sub_value|
46
+ next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
47
+
48
+ find_obj = obj.constantize.find_by(id: sub_value[col_id]['value']['el_id'])
49
+ next unless find_obj.present?
50
+
51
+ case obj
52
+ when 'Molecule'
53
+ sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_obj.molecule_svg_file)
54
+ sub_value[col_id]['value']['el_inchikey'] = find_obj.inchikey
55
+ sub_value[col_id]['value']['el_smiles'] = find_obj.cano_smiles
56
+ sub_value[col_id]['value']['el_iupac'] = find_obj.iupac_name
57
+ sub_value[col_id]['value']['el_molecular_weight'] = find_obj.molecular_weight
58
+ when 'Sample'
59
+ sub_value[col_id]['value']['el_svg'] = find_obj.get_svg_path
60
+ sub_value[col_id]['value']['el_label'] = find_obj.short_label
61
+ sub_value[col_id]['value']['el_short_label'] = find_obj.short_label
62
+ sub_value[col_id]['value']['el_name'] = find_obj.name
63
+ sub_value[col_id]['value']['el_external_label'] = find_obj.external_label
64
+ sub_value[col_id]['value']['el_molecular_weight'] = find_obj.decoupled ? find_obj.molecular_mass : find_obj.molecule.molecular_weight
65
+ end
66
+ end
67
+ end
68
+ field
69
+ end
70
+
71
+ end
72
+ end
@@ -3,60 +3,12 @@
3
3
  require 'labimotion/entities/application_entity'
4
4
  module Labimotion
5
5
  ## Segment entity
6
- class SegmentEntity < ApplicationEntity
6
+ class SegmentEntity < PropertiesEntity
7
7
  expose :id, :segment_klass_id, :element_type, :element_id, :properties, :properties_release, :uuid, :klass_uuid, :klass_label
8
8
 
9
9
  def klass_label
10
10
  object.segment_klass.label
11
11
  end
12
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
13
  end
62
14
  end
@@ -92,7 +92,7 @@ module Labimotion
92
92
  all_coll = Collection.get_all_collection_for_user(current_user.id)
93
93
  element.collections << all_coll
94
94
  element.save!
95
- element.properties = update_sample_association(element, params[:properties], current_user)
95
+ element.properties = update_sample_association(params[:properties], current_user, element)
96
96
  element.container = update_datamodel(params[:container], current_user)
97
97
  element.save!
98
98
  element.save_segments(segments: params[:segments], current_user_id: current_user.id)
@@ -105,7 +105,7 @@ module Labimotion
105
105
  def update_element_by_id(current_user, params)
106
106
  element = Labimotion::Element.find(params[:id])
107
107
  update_datamodel(params[:container], current_user)
108
- properties = update_sample_association(element, params[:properties], current_user)
108
+ properties = update_sample_association(params[:properties], current_user, element)
109
109
  params.delete(:container)
110
110
  params.delete(:properties)
111
111
  attributes = declared(params.except(:segments), include_missing: false)
@@ -6,119 +6,21 @@ module Labimotion
6
6
  extend Grape::API::Helpers
7
7
 
8
8
  def build_sample(sid, cols, current_user, cr_opt)
9
- parent_sample = Sample.find(sid)
10
-
11
- case cr_opt
12
- when 0
13
- subsample = parent_sample
14
- collections = Collection.where(id: cols).where.not(id: subsample.collections.pluck(:id))
15
- subsample.collections << collections unless collections.empty?
16
- when 1
17
- subsample = parent_sample.create_subsample(current_user, cols, true)
18
- when 2
19
- subsample = parent_sample.dup
20
- subsample.parent = nil
21
- collections = (Collection.where(id: cols) | Collection.where(user_id: current_user.id, label: 'All', is_locked: true))
22
- subsample.collections << collections
23
- subsample.container = Container.create_root_container
24
- else
25
- return nil
26
- end
27
-
28
- return nil if subsample.nil?
29
-
30
- subsample.save!
31
- subsample.reload
32
- subsample
9
+ Labimotion::SampleAssociation.build_sample(sid, cols, current_user, cr_opt)
33
10
  rescue StandardError => e
34
11
  Labimotion.log_exception(e, current_user)
35
12
  nil
36
13
  end
37
14
 
38
- def build_table_sample(element, field_tables)
39
- sds = []
40
- field_tables.each do |field|
41
- next unless field['sub_values'].present? && field['sub_fields'].present?
42
-
43
- field_table_samples = field['sub_fields'].select { |ss| ss['type'] == 'drag_sample' }
44
- next unless field_table_samples.present?
45
-
46
- col_ids = field_table_samples.map { |x| x.values[0] }
47
- col_ids.each do |col_id|
48
- field['sub_values'].each do |sub_value|
49
- next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
50
-
51
- svalue = sub_value[col_id]['value']
52
- sid = svalue['el_id']
53
- next unless sid.present?
54
-
55
- sds << sid unless svalue['is_new']
56
- next unless svalue['is_new']
57
-
58
- cr_opt = svalue['cr_opt']
59
-
60
- subsample = build_sample(sid, element.collections, current_user, cr_opt) unless sid.nil? || cr_opt.nil?
61
- next if subsample.nil?
62
-
63
- sds << subsample.id
64
- sub_value[col_id]['value']['el_id'] = subsample.id
65
- sub_value[col_id]['value']['is_new'] = false
66
- Labimotion::ElementsSample.find_or_create_by(element_id: element.id, sample_id: subsample.id)
67
- end
68
- end
69
- end
70
- sds
15
+ def build_table_sample(field_tables, current_user, element)
16
+ Labimotion::SampleAssociation.build_table_sample(field_tables, current_user, element)
71
17
  rescue StandardError => e
72
18
  Labimotion.log_exception(e, current_user)
73
19
  []
74
20
  end
75
21
 
76
- def update_sample_association(element, properties, current_user)
77
- sds = []
78
- els = []
79
- properties['layers'].keys.each do |key|
80
- layer = properties['layers'][key]
81
- field_samples = layer['fields'].select { |ss| ss['type'] == 'drag_sample' }
82
- field_samples.each do |field|
83
- idx = properties['layers'][key]['fields'].index(field)
84
- sid = field.dig('value', 'el_id')
85
- next if sid.blank?
86
-
87
- sds << sid unless properties.dig('layers', key, 'fields', idx, 'value', 'is_new') == true
88
- next unless properties.dig('layers', key, 'fields', idx, 'value', 'is_new') == true
89
-
90
- cr_opt = field.dig('value', 'cr_opt')
91
-
92
- subsample = build_sample(sid, element.collections, current_user, cr_opt) unless sid.nil? || cr_opt.nil?
93
- next if subsample.nil?
94
-
95
- sds << subsample.id
96
- properties['layers'][key]['fields'][idx]['value']['el_id'] = subsample.id
97
- properties['layers'][key]['fields'][idx]['value']['el_label'] = subsample.short_label
98
- properties['layers'][key]['fields'][idx]['value']['el_tip'] = subsample.short_label
99
- properties['layers'][key]['fields'][idx]['value']['is_new'] = false
100
- Labimotion::ElementsSample.find_or_create_by(element_id: element.id, sample_id: subsample.id)
101
- end
102
- field_tables = properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
103
- sds << build_table_sample(element, field_tables)
104
-
105
- field_elements = layer['fields'].select { |ss| ss['type'] == 'drag_element' }
106
- field_elements.each do |field|
107
- idx = properties['layers'][key]['fields'].index(field)
108
- sid = field.dig('value', 'el_id')
109
- next if sid.blank? || sid == element.id
110
-
111
- el = Labimotion::Element.find_by(id: sid)
112
- next if el.nil?
113
-
114
- Labimotion::ElementsElement.find_or_create_by(parent_id: element.id, element_id: el.id)
115
- els << el.id
116
- end
117
-
118
- end
119
- Labimotion::ElementsSample.where(element_id: element.id).where.not(sample_id: sds)&.destroy_all
120
- Labimotion::ElementsElement.where(parent_id: element.id).where.not(element_id: els&.flatten)&.destroy_all
121
- properties
22
+ def update_sample_association(properties, current_user, element)
23
+ Labimotion::SampleAssociation.update_sample_association(properties, current_user, element)
122
24
  rescue StandardError => e
123
25
  Labimotion.log_exception(e, current_user)
124
26
  end
@@ -20,7 +20,10 @@ module Labimotion
20
20
 
21
21
  def self.process_ds(id, current_user = {})
22
22
  att = Attachment.find_by(id: id, con_state: Labimotion::ConState::CONVERTED)
23
- return if att.nil? || att.attachable_id.nil? || att.attachable_type != 'Container'
23
+ return if att.nil? || att.attachable_id.nil? || att.attachable_type != 'Container' || att.filename.split('.')&.last != 'zip'
24
+
25
+ eln_ds = Container.find_by(id: att.attachable_id, container_type: 'dataset')
26
+ return if eln_ds.nil? || eln_ds.parent.nil? || eln_ds.parent&.container_type != 'analysis'
24
27
 
25
28
  dsr = []
26
29
  ols = nil
@@ -40,6 +40,8 @@ module Labimotion
40
40
  header_style = sheet.styles.add_style(sz: 12, fg_color: 'FFFFFF', bg_color: '00008B', border: { style: :thick, color: 'FF777777', edges: [:bottom] })
41
41
  sheet.add_row(['File name', res_name(id)])
42
42
  sheet.add_row(['Time', Time.now.strftime("%Y-%m-%d %H:%M:%S %Z")] )
43
+ sheet.add_row(['(This file is automatically generated by the system.)'])
44
+ sheet.add_row([''])
43
45
  sheet.add_row([''])
44
46
  sheet.add_row(['Fields description of sheet:' + ds.dataset_klass.label])
45
47
  sheet.add_row(['Fields', 'Field description'], style: header_style)
@@ -49,13 +51,11 @@ module Labimotion
49
51
  sheet.add_row(['Unit', 'The unit of the field'])
50
52
  sheet.add_row(['Name', 'The key of the field, can be used to identify the field'])
51
53
  sheet.add_row(['Type', 'The type of the field'])
52
- sheet.add_row(['From device?', '[Yes] if the field is from the device, [No] if the field is manually entered by the user, [SYS] if the field is automatically generated by the system'])
53
- sheet.add_row(['Device source', 'The source tag of the device file, available only if the ontology term is 1H NMR or 13C NMR'])
54
- sheet.add_row(['Device data', 'The original device data, can not be changed after data uploaded'])
55
- sheet.add_row([''])
54
+ sheet.add_row(['Source?', '[Device] from device, [Chemotion] from Chemotion'])
55
+ sheet.add_row(['Source identifier', 'The source identifier'])
56
+ sheet.add_row(['Source data', 'The data from Device or Chemotion, cannot be modified once a generic dataset is created'])
56
57
  sheet.add_row([''])
57
58
  sheet.add_row([''])
58
- sheet.add_row(['', '(This file is automatically generated by the system.)'])
59
59
  end
60
60
 
61
61
  def export(id)
@@ -84,29 +84,41 @@ module Labimotion
84
84
  next if field['type'] == 'dummy'
85
85
 
86
86
  type = field['type']
87
- from_device = field['device'].present? ? 'Yes' : 'No'
88
- from_device = field['system'].present? ? 'SYS' : from_device
87
+ from_device = field['device'].present? ? 'Device' : ''
88
+ from_device = field['system'].present? ? 'Chemotion' : from_device
89
89
  type = "#{field['type']}-#{field['option_layers']}" if field['type'] == 'select' || field['type'] == 'system-defined'
90
90
 
91
91
  show_value = field['value'] =~ /\A\d+,\d+\z/ ? field['value']&.gsub(',', '.') : field['value']
92
- sheet.add_row([' ', field['label'], show_value, field['value_system'], field['field'], type, from_device, field['dkey'], field['system'] || field['device']].freeze)
92
+ sheet.add_row([' ', field['label'], nil, field['value_system'], field['field'], type, from_device, field['dkey'], nil].freeze)
93
+
94
+ if %w[system-defined integer].include? field['type']
95
+ sheet.rows.last.cells[2].type = :integer
96
+ sheet.rows.last.cells[8].type = :integer
97
+ else
98
+ sheet.rows.last.cells[2].type = :string
99
+ sheet.rows.last.cells[8].type = :string
100
+ end
101
+ sheet.rows.last.cells[2].value = show_value
102
+ sheet.rows.last.cells[8].value = field['system'] || field['device']
103
+
104
+
93
105
  end
94
106
  # sheet.column_widths nil, nil, nil, nil, 0, 0, 0, 0, 0
95
107
  end
96
108
  end
97
109
 
98
110
  def spectra(id)
111
+ name_mapping = []
99
112
  wb = @xfile.workbook
100
113
  gds = Labimotion::Dataset.find_by(element_id: id, element_type: 'Container')
101
114
  cds = Container.find(id)
102
- cds_csv = cds.attachments.where(aasm_state: 'csv')
115
+ cds_csv = cds.attachments.where(aasm_state: 'csv').order(:filename)
103
116
  csv_length = cds_csv.length
104
117
  return if csv_length.zero?
105
118
  cds_csv.each_with_index do |att, idx|
106
- name = File.basename(att.filename, '.csv')
107
- name = name.slice(0, (25 - csv_length.to_s.length - 1))
108
- sheet_name = "#{name}_#{idx}"
119
+ sheet_name = "Sheet#{idx+1}"
109
120
  sheet = @xfile.workbook.add_worksheet(name: sheet_name)
121
+ name_mapping.push([sheet_name, att.filename])
110
122
 
111
123
  if Labimotion::IS_RAILS5 == true
112
124
  File.open(att.store.path) do |fi|
@@ -122,10 +134,22 @@ module Labimotion
122
134
  end
123
135
  end
124
136
  end
137
+
138
+ if name_mapping.length > 1
139
+ first_sheet = @xfile.workbook.worksheets&.first
140
+ header_style = first_sheet&.styles.add_style(sz: 12, fg_color: 'FFFFFF', bg_color: '00008B', border: { style: :thick, color: 'FF777777', edges: [:bottom] })
141
+ first_sheet&.add_row(['Sheet name', 'File name'], style: header_style)
142
+ name_mapping&.each do |mapping|
143
+ next if mapping.length < 2
144
+
145
+ @xfile.workbook.worksheets&.first&.add_row([mapping[0].to_s, mapping[1].to_s])
146
+ end
147
+ end
148
+
125
149
  end
126
150
 
127
151
  def header
128
- ['Layer Label', 'Field Label', 'Value', 'Unit', 'Name', 'Type', 'from device?', 'Device source', 'Device data'].freeze
152
+ ['Layer Label', 'Field Label', 'Value', 'Unit', 'Name', 'Type', 'Source?', 'Source identifier', 'Source data'].freeze
129
153
  end
130
154
 
131
155
  def read
@@ -10,8 +10,12 @@ module Labimotion
10
10
  att = Attachment.find_by(id: id, con_state: Labimotion::ConState::NMR)
11
11
  return if att.nil?
12
12
 
13
- content = is_brucker_binary(id)
14
- if content.nil?
13
+ result = is_brucker_binary(id)
14
+ if result[:is_bagit] == true
15
+ att.update_column(:con_state, Labimotion::ConState::CONVERTED)
16
+ Labimotion::Converter.metadata(id)
17
+ Labimotion::ConState::COMPLETED
18
+ elsif result[:metadata] == nil
15
19
  Labimotion::ConState::NONE
16
20
  else
17
21
  data = process(att, id, content)
@@ -29,7 +33,9 @@ module Labimotion
29
33
  zip_file.each do |entry|
30
34
  if entry.name.include?('/pdata/') && entry.name.include?('parm.txt')
31
35
  metadata = entry.get_input_stream.read.force_encoding('UTF-8')
32
- return metadata
36
+ return { is_bagit: false, metadata: metadata }
37
+ elsif entry.name.include?('metadata/') && entry.name.include?('converter.json')
38
+ return { is_bagit: true, metadata: nil }
33
39
  end
34
40
  end
35
41
  end
@@ -39,13 +45,15 @@ module Labimotion
39
45
  zip_file.each do |entry|
40
46
  if entry.name.include?('/pdata/') && entry.name.include?('parm.txt')
41
47
  metadata = entry.get_input_stream.read.force_encoding('UTF-8')
42
- return metadata
48
+ return { is_bagit: false, metadata: metadata }
49
+ elsif entry.name.include?('metadata/') && entry.name.include?('converter.json')
50
+ return { is_bagit: true, metadata: nil }
43
51
  end
44
52
  end
45
53
  end
46
54
  end
47
55
  end
48
- nil
56
+ { is_bagit: false, metadata: nil }
49
57
  end
50
58
 
51
59
  def self.process(att, id, content)
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ class SampleAssociation
5
+ def self.build_sample(sid, cols, current_user, cr_opt)
6
+ parent_sample = Sample.find(sid)
7
+ case cr_opt
8
+ when 0
9
+ subsample = parent_sample
10
+ collections = Collection.where(id: cols).where.not(id: subsample.collections.pluck(:id))
11
+ subsample.collections << collections unless collections.empty?
12
+ when 1
13
+ subsample = parent_sample.create_subsample(current_user, cols, true)
14
+ when 2
15
+ subsample = parent_sample.dup
16
+ subsample.parent = nil
17
+ collections = (Collection.where(id: cols) | Collection.where(user_id: current_user.id, label: 'All', is_locked: true))
18
+ subsample.collections << collections
19
+ subsample.container = Container.create_root_container
20
+ else
21
+ return nil
22
+ end
23
+
24
+ return nil if subsample.nil?
25
+
26
+ subsample.save!
27
+ subsample.reload
28
+ subsample
29
+ rescue StandardError => e
30
+ Labimotion.log_exception(e, current_user)
31
+ nil
32
+ end
33
+
34
+ def self.build_table_sample(field_tables, current_user, element = nil)
35
+ sds = []
36
+ field_tables.each do |field|
37
+ next unless field['sub_values'].present? && field['sub_fields'].present?
38
+
39
+ field_table_samples = field['sub_fields'].select { |ss| ss['type'] == 'drag_sample' }
40
+ next unless field_table_samples.present?
41
+
42
+ col_ids = field_table_samples.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
+ svalue = sub_value[col_id]['value']
48
+ sid = svalue['el_id']
49
+ next unless sid.present?
50
+
51
+ sds << sid unless svalue['is_new']
52
+ next unless svalue['is_new']
53
+
54
+ cr_opt = svalue['cr_opt']
55
+ next if element.nil?
56
+
57
+ subsample = Labimotion::SampleAssociation.build_sample(sid, element.collections, current_user, cr_opt) unless sid.nil? || cr_opt.nil?
58
+ next if subsample.nil?
59
+
60
+ sds << subsample.id
61
+ sub_value[col_id]['value']['el_id'] = subsample.id
62
+ sub_value[col_id]['value']['is_new'] = false
63
+ Labimotion::ElementsSample.find_or_create_by(element_id: element.id, sample_id: subsample.id)
64
+ end
65
+ end
66
+ end
67
+ sds
68
+ rescue StandardError => e
69
+ Labimotion.log_exception(e, current_user)
70
+ []
71
+ end
72
+
73
+ def self.update_sample_association(properties, current_user, element = nil)
74
+ sds = []
75
+ els = []
76
+ properties['layers'].keys.each do |key|
77
+ layer = properties['layers'][key]
78
+ field_samples = layer['fields'].select { |ss| ss['type'] == 'drag_sample' }
79
+ field_samples.each do |field|
80
+ idx = properties['layers'][key]['fields'].index(field)
81
+ sid = field.dig('value', 'el_id')
82
+ next if sid.blank?
83
+
84
+ sds << sid unless properties.dig('layers', key, 'fields', idx, 'value', 'is_new') == true
85
+ next unless properties.dig('layers', key, 'fields', idx, 'value', 'is_new') == true
86
+
87
+ cr_opt = field.dig('value', 'cr_opt')
88
+ subsample = Labimotion::SampleAssociation.build_sample(sid, element&.collections, current_user, cr_opt) unless sid.nil? || cr_opt.nil?
89
+ next if subsample.nil?
90
+
91
+ sds << subsample.id
92
+ properties['layers'][key]['fields'][idx]['value']['el_id'] = subsample.id
93
+ properties['layers'][key]['fields'][idx]['value']['el_label'] = subsample.short_label
94
+ properties['layers'][key]['fields'][idx]['value']['el_tip'] = subsample.short_label
95
+ properties['layers'][key]['fields'][idx]['value']['is_new'] = false
96
+ Labimotion::ElementsSample.find_or_create_by(element_id: element.id, sample_id: subsample.id) if element.present?
97
+ end
98
+ field_tables = properties['layers'][key]['fields'].select { |ss| ss['type'] == 'table' }
99
+ sds << Labimotion::SampleAssociation.build_table_sample(field_tables, current_user, element) if element.present?
100
+ field_elements = layer['fields'].select { |ss| ss['type'] == 'drag_element' }
101
+ field_elements.each do |field|
102
+ idx = properties['layers'][key]['fields'].index(field)
103
+ sid = field.dig('value', 'el_id')
104
+ next if element.nil? || sid.blank? || sid == element.id
105
+
106
+ el = Labimotion::Element.find_by(id: sid)
107
+ next if el.nil?
108
+
109
+ Labimotion::ElementsElement.find_or_create_by(parent_id: element.id, element_id: el.id)
110
+ els << el.id
111
+ end
112
+
113
+ end
114
+ if element.present?
115
+ es_list = Labimotion::ElementsSample.where(element_id: element.id).where.not(sample_id: sds)
116
+ ee_list = Labimotion::ElementsElement.where(parent_id: element.id).where.not(element_id: els&.flatten)
117
+ es_list.destroy_all if es_list.present?
118
+ ee_list.destroy_all if ee_list.present?
119
+ end
120
+ properties
121
+ rescue StandardError => e
122
+ Labimotion.log_exception(e, current_user)
123
+ end
124
+ end
125
+ end
@@ -41,6 +41,7 @@ module Labimotion
41
41
 
42
42
  def save_segments(**args) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
43
43
  return if args[:segments].nil?
44
+
44
45
  segments = []
45
46
  args[:segments]&.each do |seg|
46
47
  klass = Labimotion::SegmentKlass.find_by(id: seg['segment_klass_id'])
@@ -50,6 +51,7 @@ module Labimotion
50
51
  props['identifier'] = klass.identifier if klass.identifier.present?
51
52
  props['uuid'] = uuid
52
53
  props['klass'] = 'Segment'
54
+ props = Labimotion::SampleAssociation.update_sample_association(props, args[:current_user_id])
53
55
  segment = Labimotion::Segment.find_by(element_type: Labimotion::Utils.element_name(self.class.name), element_id: self.id, segment_klass_id: seg['segment_klass_id'])
54
56
  if segment.present? && (segment.klass_uuid != props['klass_uuid'] || segment.properties != props)
55
57
  segment.update!(properties_release: klass.properties_release, properties: props, uuid: uuid, klass_uuid: props['klass_uuid'])
@@ -3,9 +3,5 @@
3
3
  ## Labimotion Version
4
4
  module Labimotion
5
5
  IS_RAILS5 = false
6
- VERSION_ELN = '1.0.18'
7
- VERSION_REPO = '0.3.1'
8
-
9
- VERSION = Labimotion::VERSION_REPO if Labimotion::IS_RAILS5 == true
10
- VERSION = Labimotion::VERSION_ELN if Labimotion::IS_RAILS5 == false
6
+ VERSION = '1.1.0'
11
7
  end
data/lib/labimotion.rb CHANGED
@@ -8,7 +8,7 @@ module Labimotion
8
8
  end
9
9
 
10
10
  def self.log_exception(exception, current_user = nil)
11
- Labimotion.logger.error("version: #{Labimotion::VERSION}; #{Labimotion::IS_RAILS5}, (#{current_user&.id}) \n Exception: #{exception.message}")
11
+ Labimotion.logger.error("version: #{Labimotion::VERSION}; (#{current_user&.id}) \n Exception: #{exception.message}")
12
12
  Labimotion.logger.error(exception.backtrace.join("\n"))
13
13
  end
14
14
 
@@ -22,6 +22,8 @@ module Labimotion
22
22
  autoload :ConverterAPI, 'labimotion/apis/converter_api'
23
23
 
24
24
  ######## Entities
25
+ autoload :PropertiesEntity, 'labimotion/entities/properties_entity'
26
+
25
27
  autoload :ElementEntity, 'labimotion/entities/element_entity'
26
28
  autoload :ElnElementEntity, 'labimotion/entities/eln_element_entity'
27
29
 
@@ -56,6 +58,7 @@ module Labimotion
56
58
  autoload :NmrMapperRepo, 'labimotion/libs/nmr_mapper_repo' ## for Chemotion Repository
57
59
  autoload :TemplateHub, 'labimotion/libs/template_hub'
58
60
  autoload :ExportDataset, 'labimotion/libs/export_dataset'
61
+ autoload :SampleAssociation, 'labimotion/libs/sample_association'
59
62
 
60
63
  ######## Utils
61
64
  autoload :ConState, 'labimotion/utils/con_state'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: labimotion
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.18
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chia-Lin Lin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-10-20 00:00:00.000000000 Z
12
+ date: 2024-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -52,6 +52,7 @@ files:
52
52
  - lib/labimotion/entities/generic_klass_entity.rb
53
53
  - lib/labimotion/entities/generic_public_entity.rb
54
54
  - lib/labimotion/entities/klass_revision_entity.rb
55
+ - lib/labimotion/entities/properties_entity.rb
55
56
  - lib/labimotion/entities/segment_entity.rb
56
57
  - lib/labimotion/entities/segment_klass_entity.rb
57
58
  - lib/labimotion/entities/segment_revision_entity.rb
@@ -66,6 +67,7 @@ files:
66
67
  - lib/labimotion/libs/converter.rb
67
68
  - lib/labimotion/libs/export_dataset.rb
68
69
  - lib/labimotion/libs/nmr_mapper.rb
70
+ - lib/labimotion/libs/sample_association.rb
69
71
  - lib/labimotion/libs/template_hub.rb
70
72
  - lib/labimotion/models/collections_element.rb
71
73
  - lib/labimotion/models/concerns/attachment_converter.rb
@@ -97,7 +99,7 @@ files:
97
99
  - lib/labimotion/version.rb
98
100
  homepage: https://gitlab.kit.edu/kit/labimotion/labimotion
99
101
  licenses:
100
- - GPL-3.0
102
+ - AGPL-3.0
101
103
  metadata: {}
102
104
  post_install_message:
103
105
  rdoc_options: []
@@ -114,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
116
  - !ruby/object:Gem::Version
115
117
  version: '0'
116
118
  requirements: []
117
- rubygems_version: 3.4.18
119
+ rubygems_version: 3.1.6
118
120
  signing_key:
119
121
  specification_version: 4
120
122
  summary: Chemotion LabIMotion