labimotion 1.4.1 → 2.0.0.rc6
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 +4 -4
- data/lib/labimotion/apis/generic_element_api.rb +1 -0
- data/lib/labimotion/apis/generic_klass_api.rb +3 -2
- data/lib/labimotion/apis/labimotion_api.rb +13 -0
- data/lib/labimotion/apis/standard_api.rb +25 -0
- data/lib/labimotion/apis/standard_layer_api.rb +87 -0
- data/lib/labimotion/apis/vocabulary_api.rb +93 -0
- data/lib/labimotion/constants.rb +21 -0
- data/lib/labimotion/entities/dataset_entity.rb +1 -1
- data/lib/labimotion/entities/element_entity.rb +1 -0
- data/lib/labimotion/entities/properties_entity.rb +229 -56
- data/lib/labimotion/entities/segment_entity.rb +0 -1
- data/lib/labimotion/entities/vocabulary_entity.rb +28 -0
- data/lib/labimotion/helpers/element_helpers.rb +8 -6
- data/lib/labimotion/helpers/generic_helpers.rb +6 -1
- data/lib/labimotion/helpers/param_helpers.rb +121 -82
- data/lib/labimotion/helpers/segment_helpers.rb +1 -1
- data/lib/labimotion/helpers/vocabulary_helpers.rb +16 -0
- data/lib/labimotion/libs/converter.rb +12 -33
- data/lib/labimotion/libs/data/mapper/Chemwiki.json +236 -0
- data/lib/labimotion/libs/data/mapper/Source.json +78 -0
- data/lib/labimotion/libs/data/vocab/Standard.json +385 -0
- data/lib/labimotion/libs/data/vocab/System.json +131 -0
- data/lib/labimotion/libs/dataset_builder.rb +70 -0
- data/lib/labimotion/libs/export_dataset.rb +165 -66
- data/lib/labimotion/libs/nmr_mapper.rb +204 -246
- data/lib/labimotion/libs/sample_association.rb +4 -0
- data/lib/labimotion/libs/vocabulary_handler.rb +118 -0
- data/lib/labimotion/models/concerns/attachment_converter.rb +5 -4
- data/lib/labimotion/models/concerns/datasetable.rb +1 -0
- data/lib/labimotion/models/concerns/segmentable.rb +2 -0
- data/lib/labimotion/models/element.rb +3 -0
- data/lib/labimotion/models/std_layer.rb +9 -0
- data/lib/labimotion/models/std_layers_revision.rb +9 -0
- data/lib/labimotion/models/vocabulary.rb +12 -0
- data/lib/labimotion/utils/mapper_utils.rb +169 -0
- data/lib/labimotion/utils/utils.rb +22 -0
- data/lib/labimotion/version.rb +1 -1
- data/lib/labimotion.rb +13 -3
- metadata +25 -5
@@ -93,7 +93,8 @@ module Labimotion
|
|
93
93
|
all_coll = Collection.get_all_collection_for_user(current_user.id)
|
94
94
|
element.collections << all_coll
|
95
95
|
element.save!
|
96
|
-
|
96
|
+
_properties = update_sample_association(params[:properties], current_user, element)
|
97
|
+
element.properties = update_vocabularies(_properties, current_user, element)
|
97
98
|
element.container = update_datamodel(params[:container], current_user)
|
98
99
|
element.save!
|
99
100
|
update_element_labels(element, params[:user_labels], current_user.id)
|
@@ -112,7 +113,6 @@ module Labimotion
|
|
112
113
|
params.delete(:properties)
|
113
114
|
update_element_labels(element, params[:user_labels], current_user.id)
|
114
115
|
params.delete(:user_labels)
|
115
|
-
|
116
116
|
attributes = declared(params.except(:segments), include_missing: false)
|
117
117
|
properties['pkg'] = Labimotion::Utils.pkg(properties['pkg'])
|
118
118
|
if element.klass_uuid != properties['klass_uuid'] || element.properties != properties || element.name != params[:name]
|
@@ -123,15 +123,16 @@ module Labimotion
|
|
123
123
|
properties.delete('flow') unless properties['flow'].nil?
|
124
124
|
properties.delete('flowObject') unless properties['flowObject'].nil?
|
125
125
|
properties.delete('select_options') unless properties['select_options'].nil?
|
126
|
-
|
127
126
|
attributes['properties'] = properties
|
128
127
|
attributes['properties']['uuid'] = uuid
|
129
128
|
attributes['uuid'] = uuid
|
130
129
|
attributes['klass_uuid'] = properties['klass_uuid']
|
131
|
-
|
132
130
|
element.update(attributes)
|
133
131
|
end
|
134
132
|
element.save_segments(segments: params[:segments], current_user_id: current_user.id)
|
133
|
+
element.reload
|
134
|
+
element.properties = update_vocabularies(element.properties, current_user, element)
|
135
|
+
element.save!
|
135
136
|
element
|
136
137
|
rescue StandardError => e
|
137
138
|
Labimotion.log_exception(e, current_user)
|
@@ -321,7 +322,6 @@ module Labimotion
|
|
321
322
|
return { status: 'success', message: "The element: #{attributes['name']} has been created using version: #{attributes['version']}!" }
|
322
323
|
end
|
323
324
|
end
|
324
|
-
|
325
325
|
rescue StandardError => e
|
326
326
|
Labimotion.log_exception(e, current_user)
|
327
327
|
return { status: 'error', message: e.message }
|
@@ -351,7 +351,9 @@ module Labimotion
|
|
351
351
|
_att
|
352
352
|
end
|
353
353
|
attachments
|
354
|
+
rescue StandardError => e
|
355
|
+
Labimotion.log_exception(e)
|
356
|
+
attachments
|
354
357
|
end
|
355
|
-
|
356
358
|
end
|
357
359
|
end
|
@@ -9,7 +9,12 @@ module Labimotion
|
|
9
9
|
extend Grape::API::Helpers
|
10
10
|
|
11
11
|
def authenticate_admin!(type)
|
12
|
-
error!('401 Unauthorized', 401)
|
12
|
+
unauthorized = -> { error!('401 Unauthorized', 401) }
|
13
|
+
if %w[standard_layers vocabularies].include?(type)
|
14
|
+
unauthorized.call unless current_user.generic_admin.values_at('elements', 'segments', 'datasets').any?
|
15
|
+
else
|
16
|
+
unauthorized.call unless current_user.generic_admin[type]
|
17
|
+
end
|
13
18
|
end
|
14
19
|
|
15
20
|
def fetch_klass(name, id)
|
@@ -6,94 +6,133 @@ module Labimotion
|
|
6
6
|
## Generic Helpers
|
7
7
|
module ParamHelpers
|
8
8
|
extend Grape::API::Helpers
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
98
137
|
end
|
99
|
-
end
|
138
|
+
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,8 @@ 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
|
127
126
|
filename = oat.filename
|
128
127
|
name = "#{File.basename(filename, '.*')}.zip"
|
129
|
-
|
130
128
|
att = Attachment.new(
|
131
129
|
filename: name,
|
132
130
|
file_path: tmp_file.path,
|
@@ -140,7 +138,7 @@ module Labimotion
|
|
140
138
|
|
141
139
|
att.save! if att.valid?
|
142
140
|
|
143
|
-
process_ds(att.id)
|
141
|
+
process_ds(att.id, current_user)
|
144
142
|
rescue StandardError => e
|
145
143
|
raise e
|
146
144
|
ensure
|
@@ -148,7 +146,7 @@ module Labimotion
|
|
148
146
|
end
|
149
147
|
end
|
150
148
|
|
151
|
-
def self.process(data)
|
149
|
+
def self.process(data, current_user = {}) # rubocop: disable Metrics/PerceivedComplexity
|
152
150
|
return data[:a].con_state if data[:a]&.attachable_type != 'Container'
|
153
151
|
response = nil
|
154
152
|
begin
|
@@ -165,25 +163,25 @@ module Labimotion
|
|
165
163
|
)
|
166
164
|
end
|
167
165
|
if response.ok?
|
168
|
-
Labimotion::Converter.handle_response(data[:a], response)
|
166
|
+
Labimotion::Converter.handle_response(data[:a], response, current_user)
|
169
167
|
Labimotion::ConState::PROCESSED
|
170
168
|
else
|
171
169
|
Labimotion::Converter.logger.error ["Converter Response Error: id: [#{data[:a]&.id}], filename: [#{data[:a]&.filename}], response: #{response}"].join($INPUT_RECORD_SEPARATOR)
|
172
170
|
Labimotion::ConState::ERROR
|
173
171
|
end
|
174
172
|
rescue StandardError => e
|
175
|
-
Labimotion::Converter.logger.error ["process fail:
|
173
|
+
Labimotion::Converter.logger.error ["process fail: #{data[:a]&.id}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
|
176
174
|
Labimotion::ConState::ERROR
|
177
175
|
ensure
|
178
176
|
FileUtils.rm_f(ofile)
|
179
177
|
end
|
180
178
|
end
|
181
179
|
|
182
|
-
def self.jcamp_converter(id)
|
180
|
+
def self.jcamp_converter(id, current_user = {})
|
183
181
|
data = Labimotion::Converter.vor_conv(id)
|
184
182
|
return if data.nil?
|
185
183
|
|
186
|
-
Labimotion::Converter.process(data)
|
184
|
+
Labimotion::Converter.process(data, current_user)
|
187
185
|
rescue StandardError => e
|
188
186
|
Labimotion::Converter.logger.error ["jcamp_converter fail: #{id}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
|
189
187
|
Labimotion::ConState::ERROR
|
@@ -243,27 +241,8 @@ module Labimotion
|
|
243
241
|
fi['device'] = ds[:device] || ds[:value]
|
244
242
|
new_prop[Labimotion::Prop::LAYERS][ds[:layer]][Labimotion::Prop::FIELDS][idx] = fi
|
245
243
|
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
244
|
element = Container.find(dataset.element_id)&.root_element
|
254
|
-
|
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
|
245
|
+
new_prop = Labimotion::VocabularyHandler.update_vocabularies(new_prop, current_user, element)
|
267
246
|
dataset.properties = new_prop
|
268
247
|
dataset.save!
|
269
248
|
end
|
@@ -325,13 +304,13 @@ module Labimotion
|
|
325
304
|
res
|
326
305
|
end
|
327
306
|
|
328
|
-
def self.metadata(id)
|
307
|
+
def self.metadata(id, current_user)
|
329
308
|
att = Attachment.find(id)
|
330
309
|
return if att.nil? || att.attachable_id.nil? || att.attachable_type != Labimotion::Prop::CONTAINER
|
331
310
|
|
332
311
|
ds = Labimotion::Dataset.find_by(element_type: Labimotion::Prop::CONTAINER, element_id: att.attachable_id)
|
333
312
|
att.update_column(:con_state, Labimotion::ConState::COMPLETED) if ds.present?
|
334
|
-
process_ds(att.id) if ds.nil?
|
313
|
+
process_ds(att.id, current_user) if ds.nil?
|
335
314
|
end
|
336
315
|
end
|
337
316
|
end
|