Skip to content

Commit f77f4a3

Browse files
authored
feat: device description - a new element for user to define a device set up (#2281)
Add a new element manageable by users though the Element-list: Device-Description It belongs to a device and defines: - the purpose of the device using ontology (CHMO) - how the device is setup (device components description) - current configuration - responsible entities /maintenance - ... Backend: - AR model DeviceDescription (belongs to Device) - manageable through collection (has_many collections_device_descriptions, element_permission ...) - Grape api endpoints and Usecases for CRUD operations (NB Labimotion::SegmentKlass dependence /dedicated sql queries for ontologies) - DB seed Labimotion::ElementKlass where name: 'device_description' Frontend: - integration for full management by users through element-list/element-detail UI - mobx store (element-details) - fetchers CRUD, split ...
1 parent 5c56d4d commit f77f4a3

File tree

116 files changed

+6217
-183
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+6217
-183
lines changed

app/api/api.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def to_json_camel_case(val)
138138

139139
TARGET = Rails.env.production? ? 'https://www.chemotion-repository.net/' : 'http://localhost:3000/'
140140

141-
ELEMENTS = %w[research_plan screen wellplate reaction sample cell_line].freeze
141+
ELEMENTS = %w[research_plan screen wellplate reaction sample cell_line device_description].freeze
142142

143143
ELEMENT_CLASS = {
144144
'research_plan' => ResearchPlan,
@@ -147,6 +147,7 @@ def to_json_camel_case(val)
147147
'reaction' => Reaction,
148148
'sample' => Sample,
149149
'cell_line' => CelllineSample,
150+
'device_description' => DeviceDescription,
150151
}.freeze
151152

152153
mount Chemotion::LiteratureAPI
@@ -203,6 +204,7 @@ def to_json_camel_case(val)
203204
mount Chemotion::AdminDeviceAPI
204205
mount Chemotion::AdminDeviceMetadataAPI
205206
mount Chemotion::ChemicalAPI
207+
mount Chemotion::DeviceDescriptionAPI
206208

207209
if Rails.env.development?
208210
add_swagger_documentation(info: {

app/api/chemotion/attachable_api.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ class AttachableAPI < Grape::API
4848
begin
4949
a.save!
5050
attach_ary.push(a.id)
51-
rp_attach_ary.push(a.id) if a.attachable_type.in?(%w[ResearchPlan Wellplate Labimotion::Element])
51+
if a.attachable_type.in?(%w[ResearchPlan Wellplate DeviceDescription Labimotion::Element])
52+
rp_attach_ary.push(a.id)
53+
end
5254
ensure
5355
tempfile.close
5456
tempfile.unlink

app/api/chemotion/attachment_api.rb

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def remove_duplicated(att)
8282

8383
@attachment = Attachment.find_by(identifier: params[:identifier]) if @attachment.nil? && params[:identifier]
8484

85+
# rubocop:disable Performance/StringInclude
8586
case request.env['REQUEST_METHOD']
8687
when /delete/i
8788
error!('401 Unauthorized', 401) unless writable?(@attachment)
@@ -101,6 +102,13 @@ def remove_duplicated(att)
101102
can_dwnld = can_read &&
102103
ElementPermissionProxy.new(current_user, element, user_ids).read_dataset?
103104
end
105+
elsif /device_description_analyses/.match?(request.url)
106+
@device_description = DeviceDescription.find(params[:device_description_id])
107+
if (element = @device_description)
108+
can_read = ElementPolicy.new(current_user, element).read?
109+
can_dwnld = can_read &&
110+
ElementPermissionProxy.new(current_user, element, user_ids).read_dataset?
111+
end
104112
elsif @attachment
105113

106114
can_dwnld = @attachment.container_id.nil? && @attachment.created_for == current_user.id
@@ -119,6 +127,7 @@ def remove_duplicated(att)
119127
end
120128
error!('401 Unauthorized', 401) unless can_dwnld
121129
end
130+
# rubocop:enable Performance/StringInclude
122131
end
123132

124133
desc 'Bulk Delete Attachments'
@@ -347,20 +356,43 @@ def remove_duplicated(att)
347356
end
348357
end&.flatten&.reduce(:+) || 0
349358
if tts > 300_000_000
350-
DownloadAnalysesJob.perform_later(@sample.id, current_user.id, false)
359+
DownloadAnalysesJob.perform_later(@sample.id, current_user.id, false, 'sample')
351360
nil
352361
else
353362
env['api.format'] = :binary
354363
content_type('application/zip, application/octet-stream')
355364
filename = CGI.escape("#{@sample.short_label}-analytical-files.zip")
356365
header('Content-Disposition', "attachment; filename=\"#{filename}\"")
357-
zip = DownloadAnalysesJob.perform_now(@sample.id, current_user.id, true)
366+
zip = DownloadAnalysesJob.perform_now(@sample.id, current_user.id, true, 'sample')
358367
zip.rewind
359368
zip.read
360369

361370
end
362371
end
363372

373+
desc 'Download the zip attachment file by device_description_id'
374+
get 'device_description_analyses/:device_description_id' do
375+
# rubocop:disable Performance/Sum
376+
tts = @device_description.analyses&.map do |a|
377+
a.children&.map do |d|
378+
d.attachments&.map(&:filesize)
379+
end
380+
end&.flatten&.reduce(:+) || 0
381+
# rubocop:enable Performance/Sum
382+
if tts > 300_000_000
383+
DownloadAnalysesJob.perform_later(@device_description.id, current_user.id, false, 'device_description')
384+
nil
385+
else
386+
env['api.format'] = :binary
387+
content_type('application/zip, application/octet-stream')
388+
filename = CGI.escape("#{@device_description.short_label}-analytical-files.zip")
389+
header('Content-Disposition', "attachment; filename=\"#{filename}\"")
390+
zip = DownloadAnalysesJob.perform_now(@device_description.id, current_user.id, true, 'device_description')
391+
zip.rewind
392+
zip.read
393+
end
394+
end
395+
364396
desc 'Return image attachment'
365397

366398
params do

app/api/chemotion/code_log_api.rb

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,16 @@ class CodeLogAPI < Grape::API
2727
get do
2828
code = params[:code]
2929
s = code&.size || 0
30-
code_log = if s >= 39
31-
CodeLog.find(CodeCreator.digit_to_uuid(code))
32-
elsif s >= 8
33-
# TODO: use where instead of find_by ?
34-
CodeLog.where('value ~ ?', "\\A0#{code}").first
35-
elsif s == 6
36-
# TODO: use where instead of find_by ?
37-
CodeLog.find_by(value_xs: code.to_i)
38-
end
30+
code_log =
31+
if s >= 39
32+
CodeLog.find(CodeCreator.digit_to_uuid(code))
33+
elsif s >= 8
34+
# TODO: use where instead of find_by ?
35+
CodeLog.where('value ~ ?', "\\A0#{code}").first
36+
elsif s == 6
37+
# TODO: use where instead of find_by ?
38+
CodeLog.find_by(value_xs: code.to_i)
39+
end
3940

4041
if code_log.nil?
4142
error!("Element with #{code.size}-digit code #{params[:code]} not found", 404)
@@ -48,7 +49,7 @@ class CodeLogAPI < Grape::API
4849
namespace :print_codes do
4950
desc 'Build PDF with element bar & qr code'
5051
params do
51-
requires :element_type, type: String, values: %w[sample reaction wellplate screen]
52+
requires :element_type, type: String, values: %w[sample reaction wellplate screen device_description]
5253
# TODO: check coerce with type Array[Integer] not working with before do
5354
requires :ids, type: Array # , coerce_with: ->(val) { val.split(/,/).map(&:to_i) }
5455
requires :width, type: Integer
@@ -97,7 +98,7 @@ class CodeLogAPI < Grape::API
9798
namespace :print_analyses_codes do
9899
desc 'Build PDF with analyses codes of one analysis type'
99100
params do
100-
requires :element_type, type: String, values: %w[sample reaction wellplate screen]
101+
requires :element_type, type: String, values: %w[sample reaction wellplate screen device_description]
101102
requires :id, type: Integer, desc: 'Element id'
102103
requires :analyses_ids, type: Array[String]
103104
requires :size, type: String, values: %w[small big]
@@ -118,7 +119,7 @@ class CodeLogAPI < Grape::API
118119
content_type('application/pdf')
119120
header 'Content-Disposition', "attachment; filename*=UTF-8''analysis_codes_#{params[:size]}.pdf"
120121
env['api.format'] = :binary
121-
# TODO: check container type/info instead
122+
# TODO: check container type/info instead
122123
# case params[:type]
123124
# when "nmr_analysis"
124125
# body AnalysisNmrPdf.new(elements).render

app/api/chemotion/collection_api.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ class CollectionAPI < Grape::API
193193
optional :cell_line, type: Hash do
194194
use :ui_state_params
195195
end
196+
optional :device_description, type: Hash do
197+
use :ui_state_params
198+
end
196199
end
197200
requires :collection_attributes, type: Hash do
198201
requires :permission_level, type: Integer
@@ -221,6 +224,9 @@ class CollectionAPI < Grape::API
221224
cell_lines = CelllineSample.by_collection_id(@cid)
222225
.by_ui_state(params[:elements_filter][:cell_line])
223226
.for_user_n_groups(user_ids)
227+
device_descriptions = DeviceDescription.by_collection_id(@cid)
228+
.by_ui_state(params[:elements_filter][:device_description])
229+
.for_user_n_groups(user_ids)
224230
elements = {}
225231
Labimotion::ElementKlass.find_each do |klass|
226232
elements[klass.name] = Labimotion::Element.by_collection_id(@cid).by_ui_state(params[:elements_filter][klass.name]).for_user_n_groups(user_ids)
@@ -237,6 +243,7 @@ class CollectionAPI < Grape::API
237243
share_screens = ElementsPolicy.new(current_user, screens).share?
238244
share_research_plans = ElementsPolicy.new(current_user, research_plans).share?
239245
share_cell_lines = ElementsPolicy.new(current_user, cell_lines).share?
246+
share_device_descriptions = ElementsPolicy.new(current_user, device_descriptions).share?
240247
share_elements = !(elements&.length > 0)
241248
elements.each do |k, v|
242249
share_elements = ElementsPolicy.new(current_user, v).share?
@@ -249,6 +256,7 @@ class CollectionAPI < Grape::API
249256
share_screens &&
250257
share_research_plans &&
251258
share_cell_lines &&
259+
share_device_descriptions &&
252260
share_elements
253261
error!('401 Unauthorized', 401) if (!sharing_allowed || is_top_secret)
254262

@@ -258,6 +266,7 @@ class CollectionAPI < Grape::API
258266
@screen_ids = screens.pluck(:id)
259267
@research_plan_ids = research_plans.pluck(:id)
260268
@cell_line_ids = cell_lines.pluck(:id)
269+
@device_description_ids = device_descriptions.pluck(:id)
261270
@element_ids = elements&.transform_values { |v| v && v.pluck(:id) }
262271
end
263272

@@ -280,6 +289,7 @@ class CollectionAPI < Grape::API
280289
screen_ids: @screen_ids,
281290
research_plan_ids: @research_plan_ids,
282291
cell_line_ids: @cell_line_ids,
292+
device_description_ids: @device_description_ids,
283293
element_ids: @element_ids,
284294
collection_attributes: params[:collection_attributes].merge(shared_by_id: current_user.id)
285295
).execute!

app/api/chemotion/comment_api.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def find_commentable(commentable_type, commentable_id)
100100
Comment.wellplate_sections.values +
101101
Comment.screen_sections.values +
102102
Comment.research_plan_sections.values +
103+
Comment.device_description_sections.values +
103104
Comment.header_sections.values
104105
end
105106

0 commit comments

Comments
 (0)