labimotion 1.4.1 → 2.0.0.rc2

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/labimotion/apis/generic_element_api.rb +1 -0
  3. data/lib/labimotion/apis/generic_klass_api.rb +3 -2
  4. data/lib/labimotion/apis/labimotion_api.rb +13 -0
  5. data/lib/labimotion/apis/standard_api.rb +26 -0
  6. data/lib/labimotion/apis/standard_layer_api.rb +100 -0
  7. data/lib/labimotion/apis/vocabulary_api.rb +107 -0
  8. data/lib/labimotion/entities/dataset_entity.rb +2 -1
  9. data/lib/labimotion/entities/properties_entity.rb +167 -55
  10. data/lib/labimotion/entities/segment_entity.rb +1 -0
  11. data/lib/labimotion/entities/vocabulary_entity.rb +39 -0
  12. data/lib/labimotion/helpers/element_helpers.rb +8 -6
  13. data/lib/labimotion/helpers/param_helpers.rb +137 -82
  14. data/lib/labimotion/helpers/segment_helpers.rb +1 -1
  15. data/lib/labimotion/helpers/vocabulary_helpers.rb +16 -0
  16. data/lib/labimotion/libs/converter.rb +13 -33
  17. data/lib/labimotion/libs/data/vocab/Standard.json +385 -0
  18. data/lib/labimotion/libs/data/vocab/System.json +131 -0
  19. data/lib/labimotion/libs/nmr_mapper.rb +2 -1
  20. data/lib/labimotion/libs/sample_association.rb +4 -0
  21. data/lib/labimotion/libs/vocabulary_handler.rb +118 -0
  22. data/lib/labimotion/models/concerns/attachment_converter.rb +5 -4
  23. data/lib/labimotion/models/concerns/datasetable.rb +1 -0
  24. data/lib/labimotion/models/concerns/segmentable.rb +2 -0
  25. data/lib/labimotion/models/std_layer.rb +9 -0
  26. data/lib/labimotion/models/std_layers_revision.rb +9 -0
  27. data/lib/labimotion/models/vocabulary.rb +12 -0
  28. data/lib/labimotion/version.rb +1 -1
  29. data/lib/labimotion.rb +10 -0
  30. metadata +20 -5
@@ -6,94 +6,149 @@ module Labimotion
6
6
  ## Generic Helpers
7
7
  module ParamHelpers
8
8
  extend Grape::API::Helpers
9
- ## Element Klass Params
10
- params :upload_element_klass_params do
11
- requires :name, type: String, desc: 'Klass Name'
12
- optional :label, type: String, desc: 'Klass label'
13
- optional :desc, type: String, desc: 'Klass desc'
14
- optional :klass_prefix, type: String, desc: 'Klass klass_prefix'
15
- optional :icon_name, type: String, desc: 'Klass icon_name'
16
- requires :properties_template, type: Hash, desc: 'Klass template'
17
- optional :properties_release, type: Hash, desc: 'Klass release'
18
- optional :released_at, type: DateTime, desc: 'Klass released_at'
19
- requires :uuid, type: String, desc: 'Klass uuid'
20
- requires :place, type: Integer, desc: 'Klass place'
21
- requires :identifier, type: String, desc: 'Klass identifier'
22
- optional :sync_time, type: DateTime, desc: 'Klass sync_time'
23
- optional :version, type: String, desc: 'Klass version'
24
- end
9
+ ## Element Klass Params
10
+ params :upload_element_klass_params do
11
+ requires :name, type: String, desc: 'Klass Name'
12
+ optional :label, type: String, desc: 'Klass label'
13
+ optional :desc, type: String, desc: 'Klass desc'
14
+ optional :klass_prefix, type: String, desc: 'Klass klass_prefix'
15
+ optional :icon_name, type: String, desc: 'Klass icon_name'
16
+ requires :properties_template, type: Hash, desc: 'Klass template'
17
+ optional :properties_release, type: Hash, desc: 'Klass release'
18
+ optional :released_at, type: DateTime, desc: 'Klass released_at'
19
+ requires :uuid, type: String, desc: 'Klass uuid'
20
+ requires :place, type: Integer, desc: 'Klass place'
21
+ requires :identifier, type: String, desc: 'Klass identifier'
22
+ optional :sync_time, type: DateTime, desc: 'Klass sync_time'
23
+ optional :version, type: String, desc: 'Klass version'
24
+ end
25
25
 
26
- params :create_element_klass_params do
27
- requires :name, type: String, desc: 'Element Klass Name'
28
- requires :label, type: String, desc: 'Element Klass Label'
29
- requires :klass_prefix, type: String, desc: 'Element Klass Short Label Prefix'
30
- optional :icon_name, type: String, desc: 'Element Klass Icon Name'
31
- optional :desc, type: String, desc: 'Element Klass Desc'
32
- optional :properties_template, type: Hash, desc: 'Element Klass properties template'
33
- end
26
+ params :create_element_klass_params do
27
+ requires :name, type: String, desc: 'Element Klass Name'
28
+ requires :label, type: String, desc: 'Element Klass Label'
29
+ requires :klass_prefix, type: String, desc: 'Element Klass Short Label Prefix'
30
+ optional :icon_name, type: String, desc: 'Element Klass Icon Name'
31
+ optional :desc, type: String, desc: 'Element Klass Desc'
32
+ optional :properties_template, type: Hash, desc: 'Element Klass properties template'
33
+ end
34
34
 
35
- params :update_element_klass_params do
36
- requires :id, type: Integer, desc: 'Element Klass ID'
37
- optional :label, type: String, desc: 'Element Klass Label'
38
- optional :klass_prefix, type: String, desc: 'Element Klass Short Label Prefix'
39
- optional :icon_name, type: String, desc: 'Element Klass Icon Name'
40
- optional :desc, type: String, desc: 'Element Klass Desc'
41
- optional :place, type: String, desc: 'Element Klass Place'
42
- end
35
+ params :update_element_klass_params do
36
+ requires :id, type: Integer, desc: 'Element Klass ID'
37
+ optional :label, type: String, desc: 'Element Klass Label'
38
+ optional :klass_prefix, type: String, desc: 'Element Klass Short Label Prefix'
39
+ optional :icon_name, type: String, desc: 'Element Klass Icon Name'
40
+ optional :desc, type: String, desc: 'Element Klass Desc'
41
+ optional :place, type: String, desc: 'Element Klass Place'
42
+ end
43
43
 
44
- ## Element Params
45
- params :create_element_params do
46
- requires :element_klass, type: Hash
47
- requires :name, type: String
48
- optional :properties, type: Hash
49
- optional :properties_release, type: Hash
50
- optional :collection_id, type: Integer
51
- requires :container, type: Hash
52
- optional :user_labels, type: Array
53
- optional :segments, type: Array, desc: 'Segments'
54
- end
44
+ ## Element Params
45
+ params :create_element_params do
46
+ requires :element_klass, type: Hash
47
+ requires :name, type: String
48
+ optional :properties, type: Hash
49
+ optional :properties_release, type: Hash
50
+ optional :collection_id, type: Integer
51
+ requires :container, type: Hash
52
+ optional :user_labels, type: Array
53
+ optional :segments, type: Array, desc: 'Segments'
54
+ end
55
55
 
56
- params :update_element_params do
57
- requires :id, type: Integer, desc: 'element id'
58
- optional :name, type: String
59
- requires :properties, type: Hash
60
- optional :properties_release, type: Hash
61
- requires :container, type: Hash
62
- optional :user_labels, type: Array
63
- optional :segments, type: Array, desc: 'Segments'
64
- end
56
+ params :update_element_params do
57
+ requires :id, type: Integer, desc: 'element id'
58
+ optional :name, type: String
59
+ requires :properties, type: Hash
60
+ optional :properties_release, type: Hash
61
+ requires :container, type: Hash
62
+ optional :user_labels, type: Array
63
+ optional :segments, type: Array, desc: 'Segments'
64
+ end
65
65
 
66
- ## Segment Klass Params
67
- params :upload_segment_klass_params do
68
- requires :label, type: String, desc: 'Klass label'
69
- optional :desc, type: String, desc: 'Klass desc'
70
- requires :properties_template, type: Hash, desc: 'Klass template'
71
- optional :properties_release, type: Hash, desc: 'Klass release'
72
- optional :released_at, type: DateTime, desc: 'Klass released_at'
73
- requires :uuid, type: String, desc: 'Klass uuid'
74
- requires :place, type: Integer, desc: 'Klass place'
75
- requires :identifier, type: String, desc: 'Klass identifier'
76
- optional :sync_time, type: DateTime, desc: 'Klass sync_time'
77
- optional :version, type: String, desc: 'Klass version'
78
- requires :element_klass, type: Hash do
79
- use :upload_element_klass_params
80
- end
66
+ ## Segment Klass Params
67
+ params :upload_segment_klass_params do
68
+ requires :label, type: String, desc: 'Klass label'
69
+ optional :desc, type: String, desc: 'Klass desc'
70
+ requires :properties_template, type: Hash, desc: 'Klass template'
71
+ optional :properties_release, type: Hash, desc: 'Klass release'
72
+ optional :released_at, type: DateTime, desc: 'Klass released_at'
73
+ requires :uuid, type: String, desc: 'Klass uuid'
74
+ requires :place, type: Integer, desc: 'Klass place'
75
+ requires :identifier, type: String, desc: 'Klass identifier'
76
+ optional :sync_time, type: DateTime, desc: 'Klass sync_time'
77
+ optional :version, type: String, desc: 'Klass version'
78
+ requires :element_klass, type: Hash do
79
+ use :upload_element_klass_params
81
80
  end
81
+ end
82
82
 
83
- params :update_segment_klass_params do
84
- requires :id, type: Integer, desc: 'Segment Klass ID'
85
- optional :label, type: String, desc: 'Segment Klass Label'
86
- optional :desc, type: String, desc: 'Segment Klass Desc'
87
- optional :place, type: String, desc: 'Segment Klass Place', default: '100'
88
- optional :identifier, type: String, desc: 'Segment Identifier'
89
- end
83
+ params :update_segment_klass_params do
84
+ requires :id, type: Integer, desc: 'Segment Klass ID'
85
+ optional :label, type: String, desc: 'Segment Klass Label'
86
+ optional :desc, type: String, desc: 'Segment Klass Desc'
87
+ optional :place, type: String, desc: 'Segment Klass Place', default: '100'
88
+ optional :identifier, type: String, desc: 'Segment Identifier'
89
+ end
90
90
 
91
- params :create_segment_klass_params do
92
- requires :label, type: String, desc: 'Segment Klass Label'
93
- requires :element_klass, type: Integer, desc: 'Element Klass Id'
94
- optional :desc, type: String, desc: 'Segment Klass Desc'
95
- optional :place, type: String, desc: 'Segment Klass Place', default: '100'
96
- optional :properties_template, type: Hash, desc: 'Element Klass properties template'
97
- end
91
+ params :create_segment_klass_params do
92
+ requires :label, type: String, desc: 'Segment Klass Label'
93
+ requires :element_klass, type: Integer, desc: 'Element Klass Id'
94
+ optional :desc, type: String, desc: 'Segment Klass Desc'
95
+ optional :place, type: String, desc: 'Segment Klass Place', default: '100'
96
+ optional :properties_template, type: Hash, desc: 'Element Klass properties template'
97
+ end
98
+
99
+ params :create_std_layer_params do
100
+ requires :name, type: String, desc: 'Element Klass Name'
101
+ requires :label, type: String, desc: 'Element Klass Label'
102
+ requires :klass_prefix, type: String, desc: 'Element Klass Short Label Prefix'
103
+ optional :icon_name, type: String, desc: 'Element Klass Icon Name'
104
+ optional :desc, type: String, desc: 'Element Klass Desc'
105
+ optional :properties_template, type: Hash, desc: 'Element Klass properties template'
106
+ end
107
+
108
+ params :std_layer_save do
109
+ requires :key, type: String, desc: 'key'
110
+ requires :cols, type: Integer, desc: 'key'
111
+ requires :label, type: String, desc: 'Label'
112
+ optional :position, type: Integer, desc: 'position'
113
+ optional :wf_position, type: Integer, desc: 'wf position'
114
+ optional :fields, type: Array, desc: 'fields'
115
+ optional :select_options, type: Hash, desc: 'selections'
116
+ end
117
+
118
+ params :std_layer_criteria do
119
+ requires :name, type: String, desc: 'Layer name'
120
+ end
121
+
122
+ params :vocab_save do
123
+ optional :name, type: String, desc: 'field'
124
+ optional :label, type: String, desc: 'Label'
125
+ optional :term_id, type: String, desc: 'ontology term_id'
126
+ requires :ontology, type: Hash, desc: 'ontology'
127
+ optional :source, type: String, desc: 'source'
128
+ optional :source_id, type: String, desc: 'source_id'
129
+ optional :layer_id, type: String, desc: 'layer_id'
130
+ optional :sub_fields, type: Array, desc: 'sub_fields'
131
+ optional :text_sub_fields, type: Array, desc: 'text_sub_fields'
132
+ requires :field_type, type: String, desc: 'field type'
133
+ requires :voc, type: Hash, desc: 'vocabulary references'
134
+ optional :select_options, type: Hash, desc: 'selections'
135
+ optional :option_layers, type: String, desc: 'option'
136
+ end
137
+
138
+ # params :vocabulary_save do
139
+ # requires :type, type: String, desc: 'type'
140
+ # requires :field, type: String, desc: 'field'
141
+ # optional :default, type: String, desc: 'default'
142
+ # optional :description, type: String, desc: 'description'
143
+ # optional :label, type: String, desc: 'label'
144
+ # optional :position, type: Integer, desc: 'position'
145
+ # optional :ontology, type: Hash, desc: 'ontology'
146
+ # optional :required, type: Boolean, desc: 'is required?'
147
+ # optional :sub_fields, type: Array, desc: 'sub_fields'
148
+ # optional :text_sub_fields, type: Array, desc: 'text_sub_fields'
149
+ # optional :source_type, type: String, desc: 'source type'
150
+ # optional :source_id, type: String, desc: 'source id'
151
+ # optional :layer_id, type: String, desc: 'layer id'
152
+ # end
98
153
  end
99
- end
154
+ end
@@ -72,7 +72,7 @@ module Labimotion
72
72
  # el_attributes['properties_template'] = response['element_klass']['properties_release']
73
73
  # Labimotion::ElementKlass.create!(el_attributes)
74
74
  attributes['element_klass_id'] = element_klass.id
75
- segment_klass = Labimotion::SegmentKlass.find_by(identifier: attributes['identifier'])
75
+ segment_klass = Labimotion::SegmentKlass.find_by(identifier: attributes['identifier']) if attributes['identifier'].present?
76
76
  if segment_klass.present?
77
77
  if segment_klass['uuid'] == attributes['uuid'] && segment_klass['version'] == attributes['version']
78
78
  return { status: 'success', message: "This segment: #{attributes['label']} has the latest version!" }
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ # Helper for associated sample
5
+ module VocabularyHelpers
6
+ extend Grape::API::Helpers
7
+
8
+ def update_vocabularies(properties, current_user, element)
9
+ Labimotion::VocabularyHandler.update_vocabularies(properties, current_user, element)
10
+ rescue StandardError => e
11
+ Labimotion.log_exception(e, current_user)
12
+ properties
13
+ end
14
+
15
+ end
16
+ end
@@ -28,7 +28,7 @@ module Labimotion
28
28
  dsr = []
29
29
  ols = nil
30
30
  Zip::File.open(att.attachment_attacher.file.url) do |zip_file|
31
- res = Labimotion::Converter.collect_metadata(zip_file) if att.filename.split('.')&.last == 'zip'
31
+ res = Labimotion::Converter.collect_metadata(zip_file, current_user) if att.filename.split('.')&.last == 'zip'
32
32
  ols = res[:o] unless res&.dig(:o).nil?
33
33
  dsr.push(res[:d]) unless res&.dig(:d).nil?
34
34
  end
@@ -92,7 +92,7 @@ module Labimotion
92
92
  { a: oa, f: folder }
93
93
  end
94
94
 
95
- def self.collect_metadata(zip_file) # rubocop: disable Metrics/PerceivedComplexity
95
+ def self.collect_metadata(zip_file, current_user = {}) # rubocop: disable Metrics/PerceivedComplexity
96
96
  dsr = []
97
97
  ols = nil
98
98
  zip_file.each do |entry|
@@ -114,7 +114,7 @@ module Labimotion
114
114
  { d: dsr, o: ols }
115
115
  end
116
116
 
117
- def self.handle_response(oat, response) # rubocop: disable Metrics/PerceivedComplexity
117
+ def self.handle_response(oat, response, current_user = {}) # rubocop: disable Metrics/PerceivedComplexity
118
118
  dsr = []
119
119
  ols = nil
120
120
 
@@ -123,10 +123,9 @@ module Labimotion
123
123
  tmp_file.write(response.parsed_response)
124
124
  tmp_file.rewind
125
125
 
126
- name = response&.headers && response&.headers['content-disposition']&.split('=')&.last
126
+ # name = response&.headers && response&.headers['content-disposition']&.split('=')&.last
127
127
  filename = oat.filename
128
128
  name = "#{File.basename(filename, '.*')}.zip"
129
-
130
129
  att = Attachment.new(
131
130
  filename: name,
132
131
  file_path: tmp_file.path,
@@ -140,7 +139,7 @@ module Labimotion
140
139
 
141
140
  att.save! if att.valid?
142
141
 
143
- process_ds(att.id)
142
+ process_ds(att.id, current_user)
144
143
  rescue StandardError => e
145
144
  raise e
146
145
  ensure
@@ -148,7 +147,7 @@ module Labimotion
148
147
  end
149
148
  end
150
149
 
151
- def self.process(data)
150
+ def self.process(data, current_user = {}) # rubocop: disable Metrics/PerceivedComplexity
152
151
  return data[:a].con_state if data[:a]&.attachable_type != 'Container'
153
152
  response = nil
154
153
  begin
@@ -165,25 +164,25 @@ module Labimotion
165
164
  )
166
165
  end
167
166
  if response.ok?
168
- Labimotion::Converter.handle_response(data[:a], response)
167
+ Labimotion::Converter.handle_response(data[:a], response, current_user)
169
168
  Labimotion::ConState::PROCESSED
170
169
  else
171
170
  Labimotion::Converter.logger.error ["Converter Response Error: id: [#{data[:a]&.id}], filename: [#{data[:a]&.filename}], response: #{response}"].join($INPUT_RECORD_SEPARATOR)
172
171
  Labimotion::ConState::ERROR
173
172
  end
174
173
  rescue StandardError => e
175
- Labimotion::Converter.logger.error ["process fail: [#{data[:a]&.id}]", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
174
+ Labimotion::Converter.logger.error ["process fail: #{data[:a]&.id}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
176
175
  Labimotion::ConState::ERROR
177
176
  ensure
178
177
  FileUtils.rm_f(ofile)
179
178
  end
180
179
  end
181
180
 
182
- def self.jcamp_converter(id)
181
+ def self.jcamp_converter(id, current_user = {})
183
182
  data = Labimotion::Converter.vor_conv(id)
184
183
  return if data.nil?
185
184
 
186
- Labimotion::Converter.process(data)
185
+ Labimotion::Converter.process(data, current_user)
187
186
  rescue StandardError => e
188
187
  Labimotion::Converter.logger.error ["jcamp_converter fail: #{id}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
189
188
  Labimotion::ConState::ERROR
@@ -243,27 +242,8 @@ module Labimotion
243
242
  fi['device'] = ds[:device] || ds[:value]
244
243
  new_prop[Labimotion::Prop::LAYERS][ds[:layer]][Labimotion::Prop::FIELDS][idx] = fi
245
244
  end
246
- new_prop.dig(Labimotion::Prop::LAYERS, 'general', Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
247
- if fi['field'] == 'creator' && current_user.present?
248
- fi['value'] = current_user.name
249
- fi['system'] = current_user.name
250
- new_prop[Labimotion::Prop::LAYERS]['general'][Labimotion::Prop::FIELDS][idx] = fi
251
- end
252
- end
253
245
  element = Container.find(dataset.element_id)&.root_element
254
- element.present? && element&.class&.name == 'Sample' && new_prop.dig(Labimotion::Prop::LAYERS, 'sample_details', Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
255
- if fi['field'] == 'id'
256
- fi['value'] = element.id
257
- fi['system'] = element.id
258
- new_prop[Labimotion::Prop::LAYERS]['sample_details'][Labimotion::Prop::FIELDS][idx] = fi
259
- end
260
-
261
- if fi['field'] == 'label'
262
- fi['value'] = element.short_label
263
- fi['system'] = element.short_label
264
- new_prop[Labimotion::Prop::LAYERS]['sample_details'][Labimotion::Prop::FIELDS][idx] = fi
265
- end
266
- end
246
+ new_prop = Labimotion::VocabularyHandler.update_vocabularies(new_prop, current_user, element)
267
247
  dataset.properties = new_prop
268
248
  dataset.save!
269
249
  end
@@ -325,13 +305,13 @@ module Labimotion
325
305
  res
326
306
  end
327
307
 
328
- def self.metadata(id)
308
+ def self.metadata(id, current_user)
329
309
  att = Attachment.find(id)
330
310
  return if att.nil? || att.attachable_id.nil? || att.attachable_type != Labimotion::Prop::CONTAINER
331
311
 
332
312
  ds = Labimotion::Dataset.find_by(element_type: Labimotion::Prop::CONTAINER, element_id: att.attachable_id)
333
313
  att.update_column(:con_state, Labimotion::ConState::COMPLETED) if ds.present?
334
- process_ds(att.id) if ds.nil?
314
+ process_ds(att.id, current_user) if ds.nil?
335
315
  end
336
316
  end
337
317
  end