labimotion 2.1.0.rc12 → 2.1.0.rc14
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/labimotion_api.rb +3 -1
- data/lib/labimotion/apis/labimotion_hub_api.rb +83 -10
- data/lib/labimotion/constants.rb +7 -0
- data/lib/labimotion/entities/element_entity.rb +1 -0
- data/lib/labimotion/entities/klass_revision_entity.rb +4 -8
- data/lib/labimotion/libs/template_hub.rb +28 -10
- data/lib/labimotion/models/concerns/klass_revision.rb +23 -0
- data/lib/labimotion/models/dataset_klasses_revision.rb +4 -1
- data/lib/labimotion/models/element.rb +6 -0
- data/lib/labimotion/models/element_klasses_revision.rb +3 -2
- data/lib/labimotion/models/segment_klasses_revision.rb +4 -1
- data/lib/labimotion/models/template_submission.rb +52 -0
- data/lib/labimotion/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3be4d822cf9ab027e3d64f1b6356f02a6d696a6125c0db56bf8ca61e342eaabe
|
|
4
|
+
data.tar.gz: 8038b4423f9c7a26fa01c07defd715809d4698a51b6362948de4560870ab4c61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c2fe973a0fd5593246206ac697d84ae77bea51f32d1501d3fbd4dc79273d67d9ac04c54866c1cf2a952424043a1edca73591756cd5644c8156d07943bc51208
|
|
7
|
+
data.tar.gz: 70b348d0130ee3fe9cc72e829013b06357172a16f5cda79e4799dcd019d317f2561ce2910e457382904cda7fe02d36465ef58fbde0de24803990fd0b428ea5c6
|
|
@@ -11,24 +11,24 @@ module Labimotion
|
|
|
11
11
|
|
|
12
12
|
namespace :labimotion_hub do
|
|
13
13
|
namespace :list do
|
|
14
|
-
desc
|
|
14
|
+
desc 'get active generic templates'
|
|
15
15
|
params do
|
|
16
|
-
requires :klass, type: String, desc: 'Klass', values:
|
|
16
|
+
requires :klass, type: String, desc: 'Klass', values: Labimotion::Constants::Klass::ALL
|
|
17
17
|
optional :with_props, type: Boolean, desc: 'With Properties', default: false
|
|
18
18
|
end
|
|
19
19
|
get do
|
|
20
20
|
list = "Labimotion::#{params[:klass]}".constantize.where(is_active: true).where.not(released_at: nil)
|
|
21
|
-
list = list.where(is_generic: true) if params[:klass] ==
|
|
22
|
-
|
|
21
|
+
list = list.where(is_generic: true) if params[:klass] == Labimotion::Constants::Klass::ELEMENT
|
|
22
|
+
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
|
[]
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
namespace :fetch do
|
|
29
|
-
desc
|
|
29
|
+
desc 'get active generic templates'
|
|
30
30
|
params do
|
|
31
|
-
requires :klass, type: String, desc: 'Klass', values:
|
|
31
|
+
requires :klass, type: String, desc: 'Klass', values: Labimotion::Constants::Klass::ALL
|
|
32
32
|
requires :origin, type: String, desc: 'origin'
|
|
33
33
|
requires :identifier, type: String, desc: 'Identifier'
|
|
34
34
|
end
|
|
@@ -43,13 +43,16 @@ module Labimotion
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
namespace :element_klasses_name do
|
|
46
|
-
desc
|
|
46
|
+
desc 'get klasses'
|
|
47
47
|
params do
|
|
48
|
-
optional :generic_only, type: Boolean, desc:
|
|
48
|
+
optional :generic_only, type: Boolean, desc: 'list generic element only'
|
|
49
49
|
end
|
|
50
50
|
get do
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
if params[:generic_only].present? && params[:generic_only] == true
|
|
52
|
+
list = Labimotion::ElementKlass.where(is_active: true, is_generic: true)
|
|
53
|
+
else
|
|
54
|
+
list = Labimotion::ElementKlass.where(is_active: true)
|
|
55
|
+
end
|
|
53
56
|
list.pluck(:name)
|
|
54
57
|
rescue StandardError => e
|
|
55
58
|
Labimotion.log_exception(e, current_user)
|
|
@@ -57,6 +60,76 @@ module Labimotion
|
|
|
57
60
|
end
|
|
58
61
|
end
|
|
59
62
|
|
|
63
|
+
namespace :submit do
|
|
64
|
+
desc 'submit a template'
|
|
65
|
+
params do
|
|
66
|
+
requires :klass, type: String, desc: 'klass of the template',
|
|
67
|
+
values: Labimotion::Constants::Klass::ALL
|
|
68
|
+
requires :id, type: Integer, desc: 'template revision id'
|
|
69
|
+
requires :contact_email, type: String, desc: 'email of the submitter', regexp: URI::MailTo::EMAIL_REGEXP
|
|
70
|
+
requires :application, type: String, desc: 'application for the template'
|
|
71
|
+
requires :message, type: String, desc: 'message of the submission'
|
|
72
|
+
end
|
|
73
|
+
post do
|
|
74
|
+
klass = params[:klass]
|
|
75
|
+
template = "Labimotion::#{klass}esRevision".constantize.find(params[:id])
|
|
76
|
+
klass_data = "Labimotion::#{klass}Entity".constantize.represent(template.klass, displayed_in_list: true)
|
|
77
|
+
metadata = {
|
|
78
|
+
klass: {
|
|
79
|
+
klass: klass,
|
|
80
|
+
data: klass_data
|
|
81
|
+
},
|
|
82
|
+
submission: {
|
|
83
|
+
last_name: current_user.last_name,
|
|
84
|
+
first_name: current_user.first_name,
|
|
85
|
+
email: current_user.email,
|
|
86
|
+
id: current_user.id,
|
|
87
|
+
contact_email: params[:contact_email],
|
|
88
|
+
application: params[:application],
|
|
89
|
+
message: params[:message]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Submit the main template
|
|
94
|
+
result = Labimotion::TemplateHub.send_to_central_hub(klass, template.properties_release, metadata,
|
|
95
|
+
request.headers['Origin'])
|
|
96
|
+
|
|
97
|
+
# Increment submitted counter if submission was successful
|
|
98
|
+
template.increment_submitted! if result[:mc] == 'ss00'
|
|
99
|
+
|
|
100
|
+
# For SegmentKlass, also submit the associated ElementKlass
|
|
101
|
+
if klass == Labimotion::Constants::Klass::SEGMENT && result[:mc] == 'ss00'
|
|
102
|
+
element_klass = template.klass.element_klass
|
|
103
|
+
element_klass_data = Labimotion::ElementKlassEntity.represent(element_klass, displayed_in_list: true)
|
|
104
|
+
element_metadata = {
|
|
105
|
+
klass: {
|
|
106
|
+
klass: Labimotion::Constants::Klass::ELEMENT,
|
|
107
|
+
data: element_klass_data
|
|
108
|
+
},
|
|
109
|
+
submission: metadata[:submission].merge(
|
|
110
|
+
associated_submission_id: result[:data][:id]
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
element_result = Labimotion::TemplateHub.send_to_central_hub(Labimotion::Constants::Klass::ELEMENT,
|
|
115
|
+
element_klass.properties_release,
|
|
116
|
+
element_metadata, request.headers['Origin'])
|
|
117
|
+
|
|
118
|
+
# Increment the ElementKlass revision counter if submission was successful
|
|
119
|
+
if element_result[:mc] == 'ss00'
|
|
120
|
+
# Find the revision that matches the ElementKlass UUID
|
|
121
|
+
element_revision = Labimotion::ElementKlassesRevision.find_by(uuid: element_klass.uuid)
|
|
122
|
+
element_revision&.increment_submitted!
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Only return the main result; TODO: handle element_result as well
|
|
127
|
+
result
|
|
128
|
+
rescue StandardError => e
|
|
129
|
+
Labimotion.log_exception(e, current_user)
|
|
130
|
+
{ mc: 'se00', msg: e.message, data: [] }
|
|
131
|
+
end
|
|
132
|
+
end
|
|
60
133
|
end
|
|
61
134
|
end
|
|
62
135
|
end
|
data/lib/labimotion/constants.rb
CHANGED
|
@@ -21,5 +21,12 @@ module Labimotion
|
|
|
21
21
|
NMR_CONFIG = ::File.join(__dir__, 'libs', 'data', 'mapper', 'Source.json').freeze
|
|
22
22
|
WIKI_CONFIG = ::File.join(__dir__, 'libs', 'data', 'mapper', 'Chemwiki.json').freeze
|
|
23
23
|
end
|
|
24
|
+
|
|
25
|
+
module Klass
|
|
26
|
+
ELEMENT = 'ElementKlass'
|
|
27
|
+
SEGMENT = 'SegmentKlass'
|
|
28
|
+
DATASET = 'DatasetKlass'
|
|
29
|
+
ALL = [ELEMENT, SEGMENT, DATASET].freeze
|
|
30
|
+
end
|
|
24
31
|
end
|
|
25
32
|
end
|
|
@@ -2,15 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
require 'labimotion/entities/application_entity'
|
|
4
4
|
module Labimotion
|
|
5
|
-
# KlassRevisionEntity
|
|
6
5
|
class KlassRevisionEntity < Labimotion::ApplicationEntity
|
|
7
|
-
expose :id, :uuid, :
|
|
6
|
+
expose :id, :uuid, :version, :released_at, :klass_id, :submitted
|
|
7
|
+
expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
klass_id = object.segment_klass_id if object.respond_to? :segment_klass_id
|
|
12
|
-
klass_id = object.dataset_klass_id if object.respond_to? :dataset_klass_id
|
|
13
|
-
klass_id
|
|
9
|
+
def klass_id
|
|
10
|
+
object.klass&.id
|
|
14
11
|
end
|
|
15
12
|
|
|
16
13
|
def released_at
|
|
@@ -18,4 +15,3 @@ module Labimotion
|
|
|
18
15
|
end
|
|
19
16
|
end
|
|
20
17
|
end
|
|
21
|
-
|
|
@@ -5,9 +5,6 @@ require 'uri'
|
|
|
5
5
|
require 'json'
|
|
6
6
|
require 'date'
|
|
7
7
|
|
|
8
|
-
# rubocop: disable Metrics/AbcSize
|
|
9
|
-
# rubocop: disable Metrics/MethodLength
|
|
10
|
-
|
|
11
8
|
module Labimotion
|
|
12
9
|
## TemplateHub
|
|
13
10
|
class TemplateHub
|
|
@@ -18,12 +15,11 @@ module Labimotion
|
|
|
18
15
|
"#{url}api/v1/labimotion_hub/#{api_name}"
|
|
19
16
|
end
|
|
20
17
|
|
|
21
|
-
|
|
22
18
|
def self.header(opt = {})
|
|
23
19
|
opt || { timeout: 10, headers: { 'Content-Type' => 'text/json' } }
|
|
24
20
|
end
|
|
25
21
|
|
|
26
|
-
def self.handle_response(oat, response)
|
|
22
|
+
def self.handle_response(oat, response)
|
|
27
23
|
begin
|
|
28
24
|
response&.success? ? 'OK' : 'ERROR'
|
|
29
25
|
rescue StandardError => e
|
|
@@ -56,10 +52,32 @@ module Labimotion
|
|
|
56
52
|
Labimotion.log_exception(e)
|
|
57
53
|
error!('Cannot connect to Chemotion Repository', 401)
|
|
58
54
|
end
|
|
55
|
+
|
|
56
|
+
def self.send_to_central_hub(klass, template, metadata, origin)
|
|
57
|
+
body = {
|
|
58
|
+
template_klass: klass,
|
|
59
|
+
template: template,
|
|
60
|
+
metadata: metadata,
|
|
61
|
+
origin: origin
|
|
62
|
+
}
|
|
63
|
+
response = HTTParty.post(
|
|
64
|
+
Labimotion::TemplateHub.uri('template_submissions'),
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type' => 'application/json',
|
|
67
|
+
'X-Origin-URL' => origin
|
|
68
|
+
},
|
|
69
|
+
body: body.to_json,
|
|
70
|
+
timeout: 10
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if [200, 201].include?(response.code)
|
|
74
|
+
parsed_response = JSON.parse(response.body)
|
|
75
|
+
return { mc: 'ss00', data: { id: parsed_response['id'] } }
|
|
76
|
+
end
|
|
77
|
+
{ mc: 'se00', msg: "HTTP #{response.code}: #{response.message}", data: {} }
|
|
78
|
+
rescue StandardError => e
|
|
79
|
+
Labimotion.log_exception(e)
|
|
80
|
+
{ mc: 'se00', msg: "Connection failure: #{e.message}", data: {} }
|
|
81
|
+
end
|
|
59
82
|
end
|
|
60
83
|
end
|
|
61
|
-
|
|
62
|
-
# rubocop: enable Metrics/AbcSize
|
|
63
|
-
# rubocop: enable Metrics/MethodLength
|
|
64
|
-
# rubocop: enable Metrics/ClassLength
|
|
65
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Labimotion
|
|
4
|
+
# Shared concern for all Klass Revision models
|
|
5
|
+
# Provides a unified interface to access the parent klass object
|
|
6
|
+
module KlassRevision
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
# Returns the associated klass object (ElementKlass, SegmentKlass, or DatasetKlass)
|
|
10
|
+
def klass
|
|
11
|
+
return element_klass if respond_to?(:element_klass)
|
|
12
|
+
return segment_klass if respond_to?(:segment_klass)
|
|
13
|
+
return dataset_klass if respond_to?(:dataset_klass)
|
|
14
|
+
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Increments the submitted counter and saves the record
|
|
19
|
+
def increment_submitted!
|
|
20
|
+
increment!(:submitted)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'labimotion/models/concerns/klass_revision'
|
|
4
|
+
|
|
3
5
|
module Labimotion
|
|
4
6
|
class DatasetKlassesRevision < ApplicationRecord
|
|
5
7
|
self.table_name = :dataset_klasses_revisions
|
|
6
8
|
acts_as_paranoid
|
|
7
|
-
|
|
9
|
+
include KlassRevision
|
|
10
|
+
belongs_to :dataset_klass, class_name: 'Labimotion::DatasetKlass'
|
|
8
11
|
end
|
|
9
12
|
end
|
|
@@ -60,6 +60,12 @@ module Labimotion
|
|
|
60
60
|
after_create :update_counter
|
|
61
61
|
before_destroy :delete_attachment
|
|
62
62
|
|
|
63
|
+
# align with eln change on preview attachment
|
|
64
|
+
def preview_attachment
|
|
65
|
+
image_atts = attachments.select(&:type_image?)
|
|
66
|
+
image_atts[0] || attachments[0]
|
|
67
|
+
end
|
|
68
|
+
|
|
63
69
|
def user_labels
|
|
64
70
|
tag&.taggable_data&.fetch('user_labels', nil)
|
|
65
71
|
end
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'labimotion/models/concerns/workflow'
|
|
4
|
+
require 'labimotion/models/concerns/klass_revision'
|
|
4
5
|
|
|
5
6
|
module Labimotion
|
|
6
7
|
class ElementKlassesRevision < ApplicationRecord
|
|
7
8
|
acts_as_paranoid
|
|
8
9
|
self.table_name = :element_klasses_revisions
|
|
9
10
|
include Workflow
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
include KlassRevision
|
|
12
|
+
belongs_to :element_klass, class_name: 'Labimotion::ElementKlass'
|
|
12
13
|
|
|
13
14
|
def migrate_workflow
|
|
14
15
|
return if properties_release.nil? || properties_release['flow'].nil?
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'labimotion/models/concerns/klass_revision'
|
|
4
|
+
|
|
3
5
|
module Labimotion
|
|
4
6
|
class SegmentKlassesRevision < ApplicationRecord
|
|
5
7
|
acts_as_paranoid
|
|
6
8
|
self.table_name = :segment_klasses_revisions
|
|
7
|
-
|
|
9
|
+
include KlassRevision
|
|
10
|
+
belongs_to :segment_klass, class_name: 'Labimotion::SegmentKlass'
|
|
8
11
|
end
|
|
9
12
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: template_submissions
|
|
6
|
+
#
|
|
7
|
+
# id :bigint not null, primary key
|
|
8
|
+
# template_klass :string not null
|
|
9
|
+
# template :jsonb not null, default: {}
|
|
10
|
+
# metadata :jsonb not null, default: {}
|
|
11
|
+
# origin :string not null
|
|
12
|
+
# state :integer not null, default: 0
|
|
13
|
+
# created_at :datetime not null
|
|
14
|
+
# updated_at :datetime
|
|
15
|
+
# deleted_at :datetime
|
|
16
|
+
#
|
|
17
|
+
# Indexes
|
|
18
|
+
#
|
|
19
|
+
# idx_template_submissions_template (template) USING gin
|
|
20
|
+
# idx_template_submissions_metadata (metadata) USING gin
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
module Labimotion
|
|
24
|
+
class TemplateSubmission < ApplicationRecord
|
|
25
|
+
acts_as_paranoid
|
|
26
|
+
|
|
27
|
+
# State enum
|
|
28
|
+
enum state: {
|
|
29
|
+
pending: 0,
|
|
30
|
+
approved: 1,
|
|
31
|
+
rejected: 2,
|
|
32
|
+
released: 3
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Validations
|
|
36
|
+
validates :template_klass, presence: true
|
|
37
|
+
validates :template, presence: true
|
|
38
|
+
validates :metadata, presence: true
|
|
39
|
+
validates :origin, presence: true
|
|
40
|
+
|
|
41
|
+
# Scopes
|
|
42
|
+
scope :by_template_klass, ->(klass) { where(template_klass: klass) }
|
|
43
|
+
scope :by_state, ->(state) { where(state: state) }
|
|
44
|
+
scope :by_origin, ->(origin) { where(origin: origin) }
|
|
45
|
+
scope :by_email, ->(email) { where("metadata->'submission'->>'email' = ?", email) }
|
|
46
|
+
scope :by_contact_email, ->(email) { where("metadata->'submission'->>'contact_email' = ?", email) }
|
|
47
|
+
scope :by_any_email, lambda { |email|
|
|
48
|
+
where("metadata->'submission'->>'email' = ? OR metadata->'submission'->>'contact_email' = ?", email, email)
|
|
49
|
+
}
|
|
50
|
+
scope :recent, -> { order(created_at: :desc) }
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/labimotion/version.rb
CHANGED
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: 2.1.0.
|
|
4
|
+
version: 2.1.0.rc14
|
|
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: 2025-
|
|
12
|
+
date: 2025-12-04 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: caxlsx
|
|
@@ -120,6 +120,7 @@ files:
|
|
|
120
120
|
- lib/labimotion/models/concerns/generic_klass.rb
|
|
121
121
|
- lib/labimotion/models/concerns/generic_klass_revisions.rb
|
|
122
122
|
- lib/labimotion/models/concerns/generic_revisions.rb
|
|
123
|
+
- lib/labimotion/models/concerns/klass_revision.rb
|
|
123
124
|
- lib/labimotion/models/concerns/linked_properties.rb
|
|
124
125
|
- lib/labimotion/models/concerns/segmentable.rb
|
|
125
126
|
- lib/labimotion/models/concerns/workflow.rb
|
|
@@ -145,6 +146,7 @@ files:
|
|
|
145
146
|
- lib/labimotion/models/segments_revision.rb
|
|
146
147
|
- lib/labimotion/models/std_layer.rb
|
|
147
148
|
- lib/labimotion/models/std_layers_revision.rb
|
|
149
|
+
- lib/labimotion/models/template_submission.rb
|
|
148
150
|
- lib/labimotion/models/vocabulary.rb
|
|
149
151
|
- lib/labimotion/models/wellplate.rb
|
|
150
152
|
- lib/labimotion/utils/con_state.rb
|