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,38 @@
1
+ # frozen_string_literal: true
2
+ require 'grape'
3
+ module Labimotion
4
+ ## DatasetHelpers
5
+ module DatasetHelpers
6
+ extend Grape::API::Helpers
7
+
8
+ def klass_list(is_active)
9
+ if is_active == true
10
+ Labimotion::DatasetKlass.where(is_active: true).order('place') || []
11
+ else
12
+ Labimotion::DatasetKlass.all.order('place') || []
13
+ end
14
+ end
15
+
16
+ def create_repo_klass(params, current_user)
17
+ response = Labimotion::TemplateHub.fetch_identifier('DatasetKlass', params[:identifier])
18
+ attributes = response.slice('ols_term_id', 'label', 'desc', 'uuid', 'identifier') # .except(:id, :is_active, :place, :created_by, :created_at, :updated_at)
19
+ attributes['properties_template'] = response['properties_release']
20
+ attributes['place'] = ((Labimotion::DatasetKlass.all.length * 10) || 0) + 10
21
+ attributes['is_active'] = false
22
+ attributes['updated_by'] = current_user.id
23
+ attributes['sync_by'] = current_user.id
24
+ attributes['sync_time'] = DateTime.now
25
+ if Labimotion::DatasetKlass.find_by(ols_term_id: attributes['ols_term_id']).present?
26
+ ds = Labimotion::DatasetKlass.find_by(ols_term_id: attributes['ols_term_id'])
27
+ ds.update!(attributes)
28
+ else
29
+ attributes['created_by'] = current_user.id
30
+ Labimotion::DatasetKlass.create!(attributes)
31
+ end
32
+ rescue => e
33
+ Labimotion.log_exception(e, current_user)
34
+ # { error: e.message }
35
+ raise e
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,268 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grape'
4
+ require 'labimotion/version'
5
+ # require 'labimotion/models/element_klass'
6
+ module Labimotion
7
+ ## ElementHelpers
8
+ module ElementHelpers
9
+ extend Grape::API::Helpers
10
+
11
+ def klass_list(is_generic_only)
12
+ if is_generic_only == true
13
+ Labimotion::ElementKlass.where(is_active: true, is_generic: true).order('place') || []
14
+ else
15
+ Labimotion::ElementKlass.where(is_active: true).order('place') || []
16
+ end
17
+ end
18
+
19
+ def create_element_klass(current_user, params)
20
+ uuid = SecureRandom.uuid
21
+ template = { uuid: uuid, layers: {}, select_options: {} }
22
+ attributes = declared(params, include_missing: false)
23
+ attributes[:properties_template]['uuid'] = uuid if attributes[:properties_template].present?
24
+ attributes[:properties_template] = template unless attributes[:properties_template].present?
25
+ attributes[:properties_template]['eln'] = Chemotion::Application.config.version if attributes[:properties_template].present?
26
+ attributes[:properties_template]['labimotion'] = Labimotion::VERSION if attributes[:properties_template].present?
27
+ attributes[:properties_template]['klass'] = 'ElementKlass' if attributes[:properties_template].present?
28
+ attributes[:is_active] = false
29
+ attributes[:uuid] = uuid
30
+ attributes[:released_at] = DateTime.now
31
+ attributes[:properties_release] = attributes[:properties_template]
32
+ attributes[:created_by] = current_user.id
33
+
34
+ new_klass = Labimotion::ElementKlass.create!(attributes)
35
+ new_klass.reload
36
+ new_klass.create_klasses_revision(current_user.id)
37
+ klass_names_file = Rails.root.join('config', 'klasses.json')
38
+ klasses = Labimotion::ElementKlass.where(is_active: true)&.pluck(:name) || []
39
+ File.write(klass_names_file, klasses)
40
+ klasses
41
+ rescue => e
42
+ Labimotion.log_exception(e, current_user)
43
+ raise e
44
+ end
45
+
46
+ def update_element_klass(current_user, params)
47
+ place = params[:place] || 100
48
+ begin
49
+ place = place.to_i if place.present? && place.to_i == place.to_f
50
+ rescue StandardError
51
+ place = 100
52
+ end
53
+ klass = Labimotion::ElementKlass.find(params[:id])
54
+ klass.label = params[:label] if params[:label].present?
55
+ klass.klass_prefix = params[:klass_prefix] if params[:klass_prefix].present?
56
+ klass.icon_name = params[:icon_name] if params[:icon_name].present?
57
+ klass.desc = params[:desc] if params[:desc].present?
58
+ klass.place = place
59
+ klass.save!
60
+ klass
61
+ rescue => e
62
+ Labimotion.log_exception(e, current_user)
63
+ raise e
64
+ end
65
+
66
+ def create_element(current_user, params)
67
+ klass = params[:element_klass] || {}
68
+ uuid = SecureRandom.uuid
69
+ params[:properties]['uuid'] = uuid
70
+ params[:properties]['klass_uuid'] = klass[:uuid]
71
+ params[:properties]['eln'] = Chemotion::Application.config.version
72
+ params[:properties]['labimotion'] = Labimotion::VERSION
73
+ params[:properties]['klass'] = 'Element'
74
+ properties = params[:properties]
75
+ properties.delete('flow') unless properties['flow'].nil?
76
+ properties.delete('select_options') unless properties['select_options'].nil?
77
+ attributes = {
78
+ name: params[:name],
79
+ element_klass_id: klass[:id],
80
+ uuid: uuid,
81
+ klass_uuid: klass[:uuid],
82
+ properties: properties,
83
+ properties_release: params[:properties_release],
84
+ created_by: current_user.id,
85
+ }
86
+ element = Labimotion::Element.new(attributes)
87
+
88
+ if params[:collection_id]
89
+ collection = current_user.collections.find(params[:collection_id])
90
+ element.collections << collection
91
+ end
92
+ all_coll = Collection.get_all_collection_for_user(current_user.id)
93
+ element.collections << all_coll
94
+ element.save!
95
+ element.properties = update_sample_association(element, params[:properties], current_user)
96
+ element.container = update_datamodel(params[:container], current_user)
97
+ element.save!
98
+ element.save_segments(segments: params[:segments], current_user_id: current_user.id)
99
+ element
100
+ rescue => e
101
+ Labimotion.log_exception(e, current_user)
102
+ raise e
103
+ end
104
+
105
+ def update_element_by_id(current_user, params)
106
+ element = Labimotion::Element.find(params[:id])
107
+ update_datamodel(params[:container], current_user)
108
+ properties = update_sample_association(element, params[:properties], current_user)
109
+ params.delete(:container)
110
+ params.delete(:properties)
111
+ attributes = declared(params.except(:segments), include_missing: false)
112
+ properties['eln'] = Chemotion::Application.config.version
113
+ properties['labimotion'] = Labimotion::VERSION
114
+ if element.klass_uuid != properties['klass_uuid'] || element.properties != properties || element.name != params[:name]
115
+ properties['klass'] = 'Element'
116
+ uuid = SecureRandom.uuid
117
+ properties['uuid'] = uuid
118
+
119
+ properties.delete('flow') unless properties['flow'].nil?
120
+ properties.delete('select_options') unless properties['select_options'].nil?
121
+
122
+ attributes['properties'] = properties
123
+ attributes['properties']['uuid'] = uuid
124
+ attributes['uuid'] = uuid
125
+ attributes['klass_uuid'] = properties['klass_uuid']
126
+
127
+ element.update(attributes)
128
+ end
129
+ element.save_segments(segments: params[:segments], current_user_id: current_user.id)
130
+ element
131
+ rescue => e
132
+ Labimotion.log_exception(e, current_user)
133
+ raise e
134
+ end
135
+
136
+ def upload_generics_files(current_user, params)
137
+ attach_ary = []
138
+ att_ary = create_uploads(
139
+ 'Element',
140
+ params[:att_id],
141
+ params[:elfiles],
142
+ params[:elInfo],
143
+ current_user.id,
144
+ ) if params[:elfiles].present? && params[:elInfo].present?
145
+
146
+ (attach_ary << att_ary).flatten! unless att_ary&.empty?
147
+
148
+ att_ary = create_uploads(
149
+ 'Segment',
150
+ params[:att_id],
151
+ params[:sefiles],
152
+ params[:seInfo],
153
+ current_user.id
154
+ ) if params[:sefiles].present? && params[:seInfo].present?
155
+
156
+ (attach_ary << att_ary).flatten! unless att_ary&.empty?
157
+
158
+ if params[:attfiles].present? || params[:delfiles].present? then
159
+ att_ary = create_attachments(
160
+ params[:attfiles],
161
+ params[:delfiles],
162
+ params[:att_type],
163
+ params[:att_id],
164
+ params[:attfilesIdentifier],
165
+ current_user.id
166
+ )
167
+ end
168
+ (attach_ary << att_ary).flatten! unless att_ary&.empty?
169
+
170
+ if Labimotion::IS_RAILS5 == true
171
+ TransferThumbnailToPublicJob.set(queue: "transfer_thumbnail_to_public_#{current_user.id}").perform_now(attach_ary) unless attach_ary.empty?
172
+ TransferFileFromTmpJob.set(queue: "transfer_file_from_tmp_#{current_user.id}").perform_now(attach_ary) unless attach_ary.empty?
173
+ end
174
+ true
175
+ rescue => e
176
+ Labimotion.log_exception(e, current_user)
177
+ ## false
178
+ raise e
179
+ end
180
+
181
+ def element_revisions(params)
182
+ klass = Labimotion::Element.find(params[:id])
183
+ list = klass.elements_revisions unless klass.nil?
184
+ list&.sort_by(&:created_at)&.reverse
185
+ rescue => e
186
+ Labimotion.log_exception(e, current_user)
187
+ raise e
188
+ end
189
+
190
+ def list_user_elements(scope, params)
191
+ from = params[:from_date]
192
+ to = params[:to_date]
193
+ by_created_at = params[:filter_created_at] || false
194
+
195
+ if params[:sort_column]&.include?('.')
196
+ layer, field = params[:sort_column].split('.')
197
+
198
+ element_klass = Labimotion::ElementKlass.find_by(name: params[:el_type])
199
+ allowed_fields = element_klass.properties_release.dig('layers', layer, 'fields')&.pluck('field') || []
200
+
201
+ if field.in?(allowed_fields)
202
+ query = ActiveRecord::Base.sanitize_sql(
203
+ [
204
+ "LEFT JOIN LATERAL(
205
+ SELECT field->'value' AS value
206
+ FROM jsonb_array_elements(properties->'layers'->:layer->'fields') a(field)
207
+ WHERE field->>'field' = :field
208
+ ) a ON true",
209
+ { layer: layer, field: field },
210
+ ],
211
+ )
212
+ scope = scope.joins(query).order('value ASC NULLS FIRST')
213
+ else
214
+ scope = scope.order(updated_at: :desc)
215
+ end
216
+ else
217
+ scope = scope.order(updated_at: :desc)
218
+ end
219
+
220
+ scope = scope.created_time_from(Time.at(from)) if from && by_created_at
221
+ scope = scope.created_time_to(Time.at(to) + 1.day) if to && by_created_at
222
+ scope = scope.updated_time_from(Time.at(from)) if from && !by_created_at
223
+ scope = scope.updated_time_to(Time.at(to) + 1.day) if to && !by_created_at
224
+ scope
225
+ rescue => e
226
+ Labimotion.log_exception(e, current_user)
227
+ raise e
228
+ end
229
+
230
+ def list_serialized_elements(params, current_user)
231
+ collection_id =
232
+ if params[:collection_id]
233
+ Collection
234
+ .belongs_to_or_shared_by(current_user.id, current_user.group_ids)
235
+ .find_by(id: params[:collection_id])&.id
236
+ elsif params[:sync_collection_id]
237
+ current_user
238
+ .all_sync_in_collections_users
239
+ .find_by(id: params[:sync_collection_id])&.collection&.id
240
+ end
241
+
242
+ scope =
243
+ if collection_id
244
+ Labimotion::Element
245
+ .joins(:element_klass, :collections_elements)
246
+ .where(
247
+ element_klasses: { name: params[:el_type] },
248
+ collections_elements: { collection_id: collection_id },
249
+ ).includes(:tag, collections: :sync_collections_users).order('created_at DESC')
250
+ else
251
+ Labimotion::Element.none
252
+ end
253
+
254
+ ## TO DO: refactor labimotion
255
+ from = params[:from_date]
256
+ to = params[:to_date]
257
+ by_created_at = params[:filter_created_at] || false
258
+ scope = scope.created_time_from(Time.at(from)) if from && by_created_at
259
+ scope = scope.created_time_to(Time.at(to) + 1.day) if to && by_created_at
260
+ scope = scope.updated_time_from(Time.at(from)) if from && !by_created_at
261
+ scope = scope.updated_time_to(Time.at(to) + 1.day) if to && !by_created_at
262
+ scope
263
+ rescue => e
264
+ Labimotion.log_exception(e, current_user)
265
+ raise e
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+ require 'grape'
3
+ require 'labimotion/version'
4
+ # Helper for associated sample
5
+ module Labimotion
6
+ ## Generic Helpers
7
+ module GenericHelpers
8
+ extend Grape::API::Helpers
9
+
10
+ def authenticate_admin!(type)
11
+ error!('401 Unauthorized', 401) unless current_user.generic_admin[type]
12
+ end
13
+
14
+ def fetch_klass(name, id)
15
+ klz = "Labimotion::#{name}".constantize.find_by(id: id)
16
+ error!("#{name.gsub(/(Klass)/, '')} is invalid. Please re-select.", 500) if klz.nil?
17
+ klz
18
+ rescue => e
19
+ Labimotion.log_exception(e, current_user)
20
+ raise e
21
+ end
22
+
23
+ def deactivate_klass(params)
24
+ klz = fetch_klass(params[:klass], params[:id])
25
+ klz&.update!(is_active: params[:is_active])
26
+ generate_klass_file unless klz.class.name != 'ElementKlass'
27
+ klz
28
+ rescue => e
29
+ Labimotion.log_exception(e, current_user)
30
+ raise e
31
+ end
32
+
33
+ def delete_klass(params)
34
+ authenticate_admin!(params[:klass].gsub(/(Klass)/, 's').downcase)
35
+ klz = fetch_klass(params[:klass], params[:id])
36
+ klz&.destroy!
37
+ generate_klass_file unless klz.class.name != 'ElementKlass'
38
+ status 201
39
+ rescue => e
40
+ Labimotion.log_exception(e, current_user)
41
+ raise e
42
+ end
43
+
44
+ def update_template(params)
45
+ klz = fetch_klass(params[:klass], params[:id])
46
+ uuid = SecureRandom.uuid
47
+ properties = params[:properties_template]
48
+ if Labimotion::IS_RAILS5 == false
49
+ properties['uuid'] = uuid unless params[:is_release] == true && @klz.identifier.present?
50
+ else
51
+ properties['uuid'] = uuid
52
+ end
53
+ properties['eln'] = Chemotion::Application.config.version
54
+ properties['labimotion'] = Labimotion::VERSION
55
+ properties['klass'] = @klz.class.name
56
+ klz.updated_by = current_user.id
57
+ klz.properties_template = properties
58
+ klz.save!
59
+ klz.reload
60
+ klz.create_klasses_revision(current_user.id) if params[:is_release] == true
61
+ klz
62
+ rescue => e
63
+ Labimotion.log_exception(e, current_user)
64
+ raise e
65
+ end
66
+
67
+ def delete_klass_revision(params)
68
+ revision = "Labimotion::#{params[:klass]}esRevision".constantize.find(params[:id])
69
+ klass = "Labimotion::#{params[:klass]}".constantize.find_by(id: params[:klass_id]) unless revision.nil?
70
+ error!('Revision is invalid.', 404) if revision.nil?
71
+ error!('Can not delete the active revision.', 405) if revision.uuid == klass.uuid
72
+ revision&.destroy!
73
+ rescue => e
74
+ Labimotion.log_exception(e, current_user)
75
+ raise e
76
+ end
77
+
78
+ def delete_revision(params)
79
+ revision = "Labimotion::#{params[:klass]}sRevision".constantize.find(params[:id])
80
+ element = "Labimotion::#{params[:klass]}".constantize.find_by(id: params[:element_id]) unless revision.nil?
81
+ error!('Revision is invalid.', 404) if revision.nil?
82
+ error!('Can not delete the active revision.', 405) if revision.uuid == element.uuid
83
+ revision&.destroy!
84
+ rescue => e
85
+ Labimotion.log_exception(e, current_user)
86
+ raise e
87
+ end
88
+
89
+ def list_klass_revisions(params)
90
+ klass = "Labimotion::#{params[:klass]}".constantize.find_by(id: params[:id])
91
+ list = klass.send("#{params[:klass].underscore}es_revisions") unless klass.nil?
92
+ list.sort_by(&:released_at).reverse
93
+ rescue => e
94
+ Labimotion.log_exception(e, current_user)
95
+ raise e
96
+ end
97
+
98
+
99
+ ###############
100
+
101
+
102
+ def generate_klass_file
103
+ klass_dir = File.join(Rails.root, 'data')
104
+ !File.directory?(klass_dir) && FileUtils.mkdir_p(klass_dir)
105
+ klass_names_file = File.join(klass_dir, 'klasses.json')
106
+ klasses = Labimotion::ElementKlass.where(is_active: true)&.pluck(:name) || []
107
+ File.write(klass_names_file, klasses)
108
+ rescue => e
109
+ Labimotion.log_exception(e, current_user)
110
+ raise e
111
+ end
112
+
113
+ def fetch_properties_uploads(properties)
114
+ uploads = []
115
+ properties['layers'].keys.each do |key|
116
+ layer = properties['layers'][key]
117
+ field_uploads = layer['fields'].select { |ss| ss['type'] == 'upload' }
118
+ field_uploads.each do |field|
119
+ ((field['value'] && field['value']['files']) || []).each do |file|
120
+ uploads.push({ layer: key, field: field['field'], uid: file['uid'], filename: file['filename'] })
121
+ end
122
+ end
123
+ end
124
+ uploads
125
+ rescue => e
126
+ Labimotion.log_exception(e, current_user)
127
+ raise e
128
+ end
129
+
130
+ def update_properties_upload(element, properties, att, pa)
131
+ return if pa.nil?
132
+
133
+ idx = properties['layers'][pa[:layer]]['fields'].index { |fl| fl['field'] == pa[:field] }
134
+ fidx = properties['layers'][pa[:layer]]['fields'][idx]['value']['files'].index { |fi| fi['uid'] == pa[:uid] }
135
+ properties['layers'][pa[:layer]]['fields'][idx]['value']['files'][fidx]['aid'] = att.id
136
+ properties['layers'][pa[:layer]]['fields'][idx]['value']['files'][fidx]['uid'] = att.identifier
137
+ element.update_columns(properties: properties)
138
+ rescue => e
139
+ Labimotion.log_exception(e, current_user)
140
+ raise e
141
+ end
142
+
143
+ def create_uploads(type, id, files, param_info, user_id)
144
+ return if files.nil? || param_info.nil? || files.empty? || param_info.empty?
145
+
146
+ attach_ary = []
147
+ map_info = JSON.parse(param_info)
148
+ map_info&.keys&.each do |key|
149
+ next if map_info[key]['files'].empty?
150
+
151
+ if type == 'Segment'
152
+ element = Labimotion::Segment.find_by(element_id: id, segment_klass_id: key)
153
+ elsif type == 'Element'
154
+ element = Labimotion::Element.find_by(id: id)
155
+ end
156
+ next if element.nil?
157
+
158
+ uploads = fetch_properties_uploads(element.properties)
159
+
160
+ map_info[key]['files'].each do |fobj|
161
+ file = (files || []).select { |ff| ff['filename'] == fobj['uid'] }&.first
162
+ pa = uploads.select { |ss| ss[:uid] == file[:filename] }&.first || nil
163
+ next unless (tempfile = file[:tempfile])
164
+
165
+ a = Attachment.new(
166
+ bucket: file[:container_id],
167
+ filename: fobj['filename'],
168
+ con_state: Labimotion::ConState::NONE,
169
+ file_path: file[:tempfile],
170
+ created_by: user_id,
171
+ created_for: user_id,
172
+ content_type: file[:type],
173
+ attachable_type: map_info[key]['type'],
174
+ attachable_id: element.id,
175
+ )
176
+ begin
177
+ a.save!
178
+
179
+ update_properties_upload(element, element.properties, a, pa)
180
+ attach_ary.push(a.id)
181
+ ensure
182
+ tempfile.close
183
+ tempfile.unlink
184
+ end
185
+ end
186
+ element.send("#{type.downcase}s_revisions")&.last&.destroy!
187
+ element.save!
188
+ end
189
+ attach_ary
190
+ rescue => e
191
+ Labimotion.log_exception(e, current_user)
192
+ error!('Error while uploading files.', 500)
193
+ raise e
194
+ end
195
+
196
+ def create_attachments(files, del_files, type, id, user_id)
197
+ attach_ary = []
198
+ (files || []).each do |file|
199
+ next unless (tempfile = file[:tempfile])
200
+
201
+ a = Attachment.new(
202
+ bucket: file[:container_id],
203
+ filename: file[:filename],
204
+ con_state: Labimotion::ConState::NONE,
205
+ file_path: file[:tempfile],
206
+ created_by: user_id,
207
+ created_for: user_id,
208
+ content_type: file[:type],
209
+ attachable_type: type,
210
+ attachable_id: id,
211
+ )
212
+ begin
213
+ a.save!
214
+ attach_ary.push(a.id)
215
+ ensure
216
+ tempfile.close
217
+ tempfile.unlink
218
+ end
219
+ end
220
+ unless (del_files || []).empty?
221
+ Attachment.where('id IN (?) AND attachable_type = (?)', del_files.map!(&:to_i),
222
+ type).update_all(attachable_id: nil)
223
+ end
224
+ attach_ary
225
+ rescue => e
226
+ Labimotion.log_exception(e, current_user)
227
+ raise e
228
+ end
229
+
230
+ def fetch_repo_generic_template(klass, identifier)
231
+ Chemotion::Generic::Fetch::Template.exec(API::TARGET, klass, identifier)
232
+ end
233
+
234
+ def fetch_repo_generic_template_list(name = false)
235
+ Chemotion::Generic::Fetch::Template.list(API::TARGET, name)
236
+ end
237
+
238
+ def fetch_repo(name)
239
+ current_klasses = "Labimotion::#{name}".constantize.where.not(identifier: nil)&.pluck(:identifier) || []
240
+ response = Labimotion::TemplateHub.list(name)
241
+ if response && response['list'].present? && response['list'].length.positive?
242
+ filter_list = response['list']&.reject do |ds|
243
+ current_klasses.include?(ds['identifier'])
244
+ end || []
245
+ end
246
+ filter_list || []
247
+ rescue => e
248
+ Labimotion.log_exception(e, current_user)
249
+ raise e
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'grape'
3
+
4
+ module Labimotion
5
+ ## RepositoryHelpers
6
+ module RepositoryHelpers
7
+ extend Grape::API::Helpers
8
+
9
+ def copy_datsets(**args)
10
+ return if args[:dataset].nil?
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ # Helper for associated sample
5
+ module SampleAssociationHelpers
6
+ extend Grape::API::Helpers
7
+
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
33
+ rescue => e
34
+ Labimotion.log_exception(e, current_user)
35
+ nil
36
+ end
37
+
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
71
+ rescue => e
72
+ Labimotion.log_exception(e, current_user)
73
+ []
74
+ end
75
+
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
122
+ rescue => e
123
+ Labimotion.log_exception(e, current_user)
124
+ end
125
+ end
126
+ end