labimotion 2.1.0.rc13 → 2.2.0.rc1
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/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/dataset_entity.rb +1 -0
- data/lib/labimotion/entities/element_entity.rb +1 -0
- data/lib/labimotion/entities/element_revision_entity.rb +1 -1
- data/lib/labimotion/entities/generic_klass_entity.rb +1 -0
- data/lib/labimotion/entities/generic_public_entity.rb +1 -0
- data/lib/labimotion/entities/klass_revision_entity.rb +5 -8
- data/lib/labimotion/entities/segment_entity.rb +1 -0
- data/lib/labimotion/entities/segment_revision_entity.rb +1 -1
- data/lib/labimotion/helpers/dataset_helpers.rb +1 -1
- data/lib/labimotion/helpers/element_helpers.rb +2 -1
- data/lib/labimotion/helpers/generic_helpers.rb +1 -0
- data/lib/labimotion/helpers/param_helpers.rb +2 -0
- data/lib/labimotion/helpers/segment_helpers.rb +1 -1
- data/lib/labimotion/libs/template_hub.rb +28 -10
- data/lib/labimotion/models/concerns/datasetable.rb +8 -5
- data/lib/labimotion/models/concerns/generic_klass_revisions.rb +2 -1
- data/lib/labimotion/models/concerns/generic_revisions.rb +2 -1
- data/lib/labimotion/models/concerns/klass_revision.rb +23 -0
- data/lib/labimotion/models/concerns/metadata_validation.rb +34 -0
- data/lib/labimotion/models/concerns/segmentable.rb +2 -2
- data/lib/labimotion/models/dataset_klass.rb +2 -0
- data/lib/labimotion/models/dataset_klasses_revision.rb +6 -1
- data/lib/labimotion/models/element_klass.rb +2 -0
- data/lib/labimotion/models/element_klasses_revision.rb +5 -2
- data/lib/labimotion/models/segment_klass.rb +2 -0
- data/lib/labimotion/models/segment_klasses_revision.rb +6 -1
- data/lib/labimotion/models/template_submission.rb +52 -0
- data/lib/labimotion/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4397eed28e8f2c6f0e21e022191d842dbb7a42000a2efe72731a89ab8bf9e77b
|
|
4
|
+
data.tar.gz: 3ae429541da0f787d6d0f544307b5acfbf3e922d83c7fc7cd27e47738eb5880e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 12a5d77d600daaf1a45640ab5ff7d253a608cd683fac28a5286019a7990e85cb7c1f0c957240fab625d3dbb703196dcb918b652bcc86457c6ac88cc085990ea0
|
|
7
|
+
data.tar.gz: 28453642570e3e177c0c2684590cdb715016c4043645d9f2e097eca0a4f41e9e3ff30564df8a0b7d5800bfb36a2fd224aa40cb91a107a2bc53adddc1db133070
|
|
@@ -378,6 +378,7 @@ module Labimotion
|
|
|
378
378
|
requires :klass, type: String, desc: 'Klass', values: %w[ElementKlass SegmentKlass DatasetKlass]
|
|
379
379
|
requires :id, type: Integer, desc: 'Klass ID'
|
|
380
380
|
requires :properties_template, type: Hash
|
|
381
|
+
optional :metadata, type: Hash, default: {}
|
|
381
382
|
optional :release, type: String, default: 'draft', desc: 'release status', values: %w[draft major minor patch]
|
|
382
383
|
end
|
|
383
384
|
after_validation do
|
|
@@ -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
|
|
@@ -9,6 +9,7 @@ module Labimotion
|
|
|
9
9
|
expose :klass_ols, :klass_label, :klass_uuid
|
|
10
10
|
expose :properties, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
11
11
|
expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
12
|
+
expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
12
13
|
|
|
13
14
|
def klass_ols
|
|
14
15
|
object&.dataset_klass&.ols_term_id
|
|
@@ -4,7 +4,7 @@ require 'labimotion/entities/application_entity'
|
|
|
4
4
|
module Labimotion
|
|
5
5
|
# ElementRevisionEntity
|
|
6
6
|
class ElementRevisionEntity < Labimotion::ApplicationEntity
|
|
7
|
-
expose :id, :element_id, :uuid, :name, :klass_uuid, :properties, :created_at
|
|
7
|
+
expose :id, :element_id, :uuid, :name, :klass_uuid, :properties, :metadata, :created_at
|
|
8
8
|
def created_at
|
|
9
9
|
object.created_at.strftime('%d.%m.%Y, %H:%M')
|
|
10
10
|
end
|
|
@@ -8,6 +8,7 @@ module Labimotion
|
|
|
8
8
|
|
|
9
9
|
expose :properties_template, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
10
10
|
expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
11
|
+
expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
11
12
|
expose_timestamps(timestamp_fields: %i[released_at created_at updated_at sync_time])
|
|
12
13
|
end
|
|
13
14
|
end
|
|
@@ -18,6 +18,7 @@ module Labimotion
|
|
|
18
18
|
expose! :version
|
|
19
19
|
expose! :released_at
|
|
20
20
|
expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
21
|
+
expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
21
22
|
expose :element_klass do |obj|
|
|
22
23
|
if obj[:element_klass_id]
|
|
23
24
|
{ label: obj.element_klass.label, icon_name: obj.element_klass.icon_name, id: obj.element_klass_id }
|
|
@@ -2,15 +2,13 @@
|
|
|
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
|
+
expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
8
9
|
|
|
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
|
|
10
|
+
def klass_id
|
|
11
|
+
object.klass&.id
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def released_at
|
|
@@ -18,4 +16,3 @@ module Labimotion
|
|
|
18
16
|
end
|
|
19
17
|
end
|
|
20
18
|
end
|
|
21
|
-
|
|
@@ -8,6 +8,7 @@ module Labimotion
|
|
|
8
8
|
expose :id, :segment_klass_id, :element_type, :element_id, :uuid, :klass_uuid, :klass_label
|
|
9
9
|
expose :properties, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
10
10
|
expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
11
|
+
expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
11
12
|
|
|
12
13
|
def klass_label
|
|
13
14
|
object.segment_klass.label
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require 'labimotion/entities/application_entity'
|
|
4
4
|
module Labimotion
|
|
5
5
|
class SegmentRevisionEntity < Labimotion::ApplicationEntity
|
|
6
|
-
expose :id, :segment_id, :uuid, :klass_uuid, :properties, :created_at
|
|
6
|
+
expose :id, :segment_id, :uuid, :klass_uuid, :properties, :metadata, :created_at
|
|
7
7
|
def created_at
|
|
8
8
|
object.created_at.strftime('%d.%m.%Y, %H:%M')
|
|
9
9
|
end
|
|
@@ -17,7 +17,7 @@ module Labimotion
|
|
|
17
17
|
|
|
18
18
|
def create_repo_klass(params, current_user, origin)
|
|
19
19
|
response = Labimotion::TemplateHub.fetch_identifier('DatasetKlass', params[:identifier], origin)
|
|
20
|
-
attributes = response.slice('ols_term_id', 'label', 'desc', 'uuid', 'identifier', 'properties_release', 'version') # .except(:id, :is_active, :place, :created_by, :created_at, :updated_at)
|
|
20
|
+
attributes = response.slice('ols_term_id', 'label', 'desc', 'uuid', 'identifier', 'properties_release', 'version', 'metadata') # .except(:id, :is_active, :place, :created_by, :created_at, :updated_at)
|
|
21
21
|
attributes['properties_release']['identifier'] = attributes['identifier']
|
|
22
22
|
attributes['properties_template'] = attributes['properties_release']
|
|
23
23
|
attributes['place'] = ((Labimotion::DatasetKlass.all.length * 10) || 0) + 10
|
|
@@ -128,6 +128,7 @@ module Labimotion
|
|
|
128
128
|
attributes['properties']['uuid'] = uuid
|
|
129
129
|
attributes['uuid'] = uuid
|
|
130
130
|
attributes['klass_uuid'] = properties['klass_uuid']
|
|
131
|
+
attributes['updated_at'] = Time.current
|
|
131
132
|
element.update_columns(attributes)
|
|
132
133
|
end
|
|
133
134
|
# element.save_segments(segments: params[:segments], current_user_id: current_user.id)
|
|
@@ -333,7 +334,7 @@ module Labimotion
|
|
|
333
334
|
|
|
334
335
|
def create_repo_klass(params, current_user, origin)
|
|
335
336
|
response = Labimotion::TemplateHub.fetch_identifier('ElementKlass', params[:identifier], origin)
|
|
336
|
-
attributes = response.slice('name', 'label', 'desc', 'icon_name', 'uuid', 'klass_prefix', 'is_generic', 'identifier', 'properties_release', 'version')
|
|
337
|
+
attributes = response.slice('name', 'label', 'desc', 'icon_name', 'uuid', 'klass_prefix', 'is_generic', 'identifier', 'properties_release', 'version', 'metadata')
|
|
337
338
|
attributes['properties_release']['identifier'] = attributes['identifier']
|
|
338
339
|
attributes['properties_template'] = attributes['properties_release']
|
|
339
340
|
attributes['place'] = ((Labimotion::ElementKlass.all.length * 10) || 0) + 10
|
|
@@ -60,6 +60,7 @@ module Labimotion
|
|
|
60
60
|
properties.delete('eln') if properties['eln'].present?
|
|
61
61
|
klz.updated_by = current_user.id
|
|
62
62
|
klz.properties_template = properties
|
|
63
|
+
klz.metadata = params[:metadata] || {}
|
|
63
64
|
klz.save!
|
|
64
65
|
klz.reload
|
|
65
66
|
klz.create_klasses_revision(current_user) if params[:release] != 'draft'
|
|
@@ -47,6 +47,7 @@ module Labimotion
|
|
|
47
47
|
requires :name, type: String
|
|
48
48
|
optional :properties, type: Hash
|
|
49
49
|
optional :properties_release, type: Hash
|
|
50
|
+
optional :metadata, type: Hash
|
|
50
51
|
optional :collection_id, type: Integer
|
|
51
52
|
requires :container, type: Hash
|
|
52
53
|
optional :user_labels, type: Array
|
|
@@ -58,6 +59,7 @@ module Labimotion
|
|
|
58
59
|
optional :name, type: String
|
|
59
60
|
requires :properties, type: Hash
|
|
60
61
|
optional :properties_release, type: Hash
|
|
62
|
+
optional :metadata, type: Hash
|
|
61
63
|
requires :container, type: Hash
|
|
62
64
|
optional :user_labels, type: Array
|
|
63
65
|
optional :segments, type: Array, desc: 'Segments'
|
|
@@ -99,7 +99,7 @@ module Labimotion
|
|
|
99
99
|
|
|
100
100
|
def create_repo_klass(params, current_user, origin)
|
|
101
101
|
response = Labimotion::TemplateHub.fetch_identifier('SegmentKlass', params[:identifier], origin)
|
|
102
|
-
attributes = response.slice('label', 'desc', 'uuid', 'identifier', 'released_at', 'properties_release', 'version')
|
|
102
|
+
attributes = response.slice('label', 'desc', 'uuid', 'identifier', 'released_at', 'properties_release', 'version', 'metadata')
|
|
103
103
|
attributes['properties_release']['identifier'] = attributes['identifier']
|
|
104
104
|
attributes['properties_template'] = attributes['properties_release']
|
|
105
105
|
attributes['place'] = ((Labimotion::SegmentKlass.all.length * 10) || 0) + 10
|
|
@@ -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
|
|
@@ -32,26 +32,29 @@ module Labimotion
|
|
|
32
32
|
)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def save_dataset(**
|
|
35
|
+
def save_dataset(**dataset_args)
|
|
36
36
|
return if not_dataset?
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
args = dataset_args[:dataset]
|
|
39
|
+
dataset_klass_id = args[:dataset_klass_id]
|
|
40
|
+
klass = Labimotion::DatasetKlass.find_by(id: dataset_klass_id)
|
|
39
41
|
uuid = SecureRandom.uuid
|
|
42
|
+
metadata = args[:metadata] || {}
|
|
40
43
|
props = args[:properties]
|
|
41
44
|
props['pkg'] = Labimotion::Utils.pkg(props['pkg'])
|
|
42
45
|
props['identifier'] = klass.identifier if klass.identifier.present?
|
|
43
46
|
props['uuid'] = uuid
|
|
44
47
|
props['klass'] = 'Dataset'
|
|
45
48
|
props['klass_uuid'] = klass.uuid
|
|
46
|
-
props = Labimotion::VocabularyHandler.update_vocabularies(props,
|
|
49
|
+
props = Labimotion::VocabularyHandler.update_vocabularies(props, dataset_args[:current_user], dataset_args[:element])
|
|
47
50
|
|
|
48
51
|
ds = Labimotion::Dataset.find_by(element_type: self.class.name, element_id: id)
|
|
49
52
|
if ds.present? && (ds.klass_uuid != klass.uuid || ds.properties != props)
|
|
50
|
-
ds.update!(properties_release: klass.properties_release, uuid: uuid, dataset_klass_id:
|
|
53
|
+
ds.update!(properties_release: klass.properties_release, uuid: uuid, dataset_klass_id: dataset_klass_id, properties: props, klass_uuid: klass.uuid)
|
|
51
54
|
end
|
|
52
55
|
return if ds.present?
|
|
53
56
|
|
|
54
|
-
Labimotion::Dataset.create!(properties_release: klass.properties_release, uuid: uuid, dataset_klass_id:
|
|
57
|
+
Labimotion::Dataset.create!(properties_release: klass.properties_release, uuid: uuid, dataset_klass_id: dataset_klass_id, element_type: self.class.name, element_id: id, properties: props, klass_uuid: klass.uuid, metadata: metadata)
|
|
55
58
|
end
|
|
56
59
|
|
|
57
60
|
def destroy_datasetable
|
|
@@ -45,7 +45,8 @@ module Labimotion
|
|
|
45
45
|
version: version,
|
|
46
46
|
created_by: updated_by,
|
|
47
47
|
properties_release: properties_release,
|
|
48
|
-
released_at: released_at
|
|
48
|
+
released_at: released_at,
|
|
49
|
+
metadata: metadata
|
|
49
50
|
}
|
|
50
51
|
attributes["#{self.class.name.underscore.split('/').last}_id"] = id
|
|
51
52
|
"#{self.class.name}esRevision".constantize.create(attributes)
|
|
@@ -22,7 +22,8 @@ module Labimotion
|
|
|
22
22
|
klass_uuid: klass_uuid,
|
|
23
23
|
properties: properties,
|
|
24
24
|
## created_by: user_for_revision&.id,
|
|
25
|
-
properties_release: properties_release
|
|
25
|
+
properties_release: properties_release,
|
|
26
|
+
metadata: metadata
|
|
26
27
|
}
|
|
27
28
|
attributes["#{Labimotion::Utils.element_name_dc(self.class.name)}_id"] = id
|
|
28
29
|
attributes['name'] = name if self.class.name == 'Labimotion::Element'
|
|
@@ -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
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Labimotion
|
|
4
|
+
## Metadata Validation Concern
|
|
5
|
+
module MetadataValidation
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
validate :metadata_must_be_hash
|
|
10
|
+
|
|
11
|
+
# Provide default value for metadata to support migrations
|
|
12
|
+
# when the column might not exist yet
|
|
13
|
+
after_initialize :set_metadata_default
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def set_metadata_default
|
|
19
|
+
self.metadata ||= {} if has_attribute?(:metadata)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def metadata_must_be_hash
|
|
23
|
+
# Skip validation if the metadata column doesn't exist yet (during migrations)
|
|
24
|
+
return unless has_attribute?(:metadata)
|
|
25
|
+
|
|
26
|
+
# Set default if nil
|
|
27
|
+
self.metadata ||= {}
|
|
28
|
+
|
|
29
|
+
return if metadata.is_a?(Hash)
|
|
30
|
+
|
|
31
|
+
errors.add(:metadata, 'must be a hash/object, not an array or other type')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -68,14 +68,14 @@ module Labimotion
|
|
|
68
68
|
# props = Labimotion::VocabularyHandler.update_vocabularies(props, current_user, self)
|
|
69
69
|
segment = Labimotion::Segment.where(element_type: self.class.name, element_id: self.id, segment_klass_id: seg['segment_klass_id']).order(id: :desc).first
|
|
70
70
|
if segment.present? && (segment.klass_uuid != props['klass_uuid'] || segment.properties != props)
|
|
71
|
-
segment.update!(properties_release: klass.properties_release, properties: props, uuid: uuid, klass_uuid: props['klass_uuid'])
|
|
71
|
+
segment.update!(properties_release: klass.properties_release, properties: props, uuid: uuid, klass_uuid: props['klass_uuid'], metadata: seg['metadata'] || {})
|
|
72
72
|
# segments.push(segment)
|
|
73
73
|
Labimotion::Segment.where(element_type: self.class.name, element_id: self.id, segment_klass_id: seg['segment_klass_id']).where.not(id: segment.id).destroy_all
|
|
74
74
|
end
|
|
75
75
|
next if segment.present?
|
|
76
76
|
|
|
77
77
|
props['klass_uuid'] = klass.uuid
|
|
78
|
-
segment = Labimotion::Segment.create!(properties_release: klass.properties_release, segment_klass_id: seg['segment_klass_id'], element_type: self.class.name, element_id: self.id, properties: props, created_by: args[:current_user_id], uuid: uuid, klass_uuid: klass.uuid)
|
|
78
|
+
segment = Labimotion::Segment.create!(properties_release: klass.properties_release, segment_klass_id: seg['segment_klass_id'], element_type: self.class.name, element_id: self.id, properties: props, created_by: args[:current_user_id], uuid: uuid, klass_uuid: klass.uuid, metadata: seg['metadata'] || {})
|
|
79
79
|
# segments.push(segment)
|
|
80
80
|
end
|
|
81
81
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'labimotion/models/concerns/generic_klass_revisions'
|
|
4
4
|
require 'labimotion/models/concerns/generic_klass'
|
|
5
|
+
require 'labimotion/models/concerns/metadata_validation'
|
|
5
6
|
|
|
6
7
|
module Labimotion
|
|
7
8
|
class DatasetKlass < ApplicationRecord
|
|
@@ -9,6 +10,7 @@ module Labimotion
|
|
|
9
10
|
self.table_name = :dataset_klasses
|
|
10
11
|
include GenericKlassRevisions
|
|
11
12
|
include GenericKlass
|
|
13
|
+
include MetadataValidation
|
|
12
14
|
|
|
13
15
|
has_many :datasets, dependent: :destroy, class_name: 'Labimotion::Dataset'
|
|
14
16
|
has_many :dataset_klasses_revisions, dependent: :destroy, class_name: 'Labimotion::DatasetKlassesRevision'
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'labimotion/models/concerns/klass_revision'
|
|
4
|
+
require 'labimotion/models/concerns/metadata_validation'
|
|
5
|
+
|
|
3
6
|
module Labimotion
|
|
4
7
|
class DatasetKlassesRevision < ApplicationRecord
|
|
5
8
|
self.table_name = :dataset_klasses_revisions
|
|
6
9
|
acts_as_paranoid
|
|
7
|
-
|
|
10
|
+
include KlassRevision
|
|
11
|
+
include MetadataValidation
|
|
12
|
+
belongs_to :dataset_klass, class_name: 'Labimotion::DatasetKlass'
|
|
8
13
|
end
|
|
9
14
|
end
|
|
@@ -4,6 +4,7 @@ require 'labimotion/conf'
|
|
|
4
4
|
require 'labimotion/models/concerns/generic_klass_revisions'
|
|
5
5
|
require 'labimotion/models/concerns/generic_klass'
|
|
6
6
|
require 'labimotion/models/concerns/workflow'
|
|
7
|
+
require 'labimotion/models/concerns/metadata_validation'
|
|
7
8
|
|
|
8
9
|
module Labimotion
|
|
9
10
|
class ElementKlass < ApplicationRecord
|
|
@@ -12,6 +13,7 @@ module Labimotion
|
|
|
12
13
|
include GenericKlassRevisions
|
|
13
14
|
include GenericKlass
|
|
14
15
|
include Workflow
|
|
16
|
+
include MetadataValidation
|
|
15
17
|
has_many :elements, dependent: :destroy, class_name: 'Labimotion::Element'
|
|
16
18
|
has_many :segment_klasses, dependent: :destroy, class_name: 'Labimotion::SegmentKlass'
|
|
17
19
|
has_many :element_klasses_revisions, dependent: :destroy, class_name: 'Labimotion::ElementKlassesRevision'
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'labimotion/models/concerns/workflow'
|
|
4
|
+
require 'labimotion/models/concerns/klass_revision'
|
|
5
|
+
require 'labimotion/models/concerns/metadata_validation'
|
|
4
6
|
|
|
5
7
|
module Labimotion
|
|
6
8
|
class ElementKlassesRevision < ApplicationRecord
|
|
7
9
|
acts_as_paranoid
|
|
8
10
|
self.table_name = :element_klasses_revisions
|
|
9
11
|
include Workflow
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
include KlassRevision
|
|
13
|
+
include MetadataValidation
|
|
14
|
+
belongs_to :element_klass, class_name: 'Labimotion::ElementKlass'
|
|
12
15
|
|
|
13
16
|
def migrate_workflow
|
|
14
17
|
return if properties_release.nil? || properties_release['flow'].nil?
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'labimotion/models/concerns/generic_klass_revisions'
|
|
4
4
|
require 'labimotion/models/concerns/generic_klass'
|
|
5
5
|
require 'labimotion/models/concerns/workflow'
|
|
6
|
+
require 'labimotion/models/concerns/metadata_validation'
|
|
6
7
|
|
|
7
8
|
module Labimotion
|
|
8
9
|
class SegmentKlass < ApplicationRecord
|
|
@@ -11,6 +12,7 @@ module Labimotion
|
|
|
11
12
|
include GenericKlassRevisions
|
|
12
13
|
include GenericKlass
|
|
13
14
|
include Workflow
|
|
15
|
+
include MetadataValidation
|
|
14
16
|
belongs_to :element_klass, class_name: 'Labimotion::ElementKlass'
|
|
15
17
|
has_many :segments, dependent: :destroy, class_name: 'Labimotion::Segment'
|
|
16
18
|
has_many :segment_klasses_revisions, dependent: :destroy, class_name: 'Labimotion::SegmentKlassesRevision'
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'labimotion/models/concerns/klass_revision'
|
|
4
|
+
require 'labimotion/models/concerns/metadata_validation'
|
|
5
|
+
|
|
3
6
|
module Labimotion
|
|
4
7
|
class SegmentKlassesRevision < ApplicationRecord
|
|
5
8
|
acts_as_paranoid
|
|
6
9
|
self.table_name = :segment_klasses_revisions
|
|
7
|
-
|
|
10
|
+
include KlassRevision
|
|
11
|
+
include MetadataValidation
|
|
12
|
+
belongs_to :segment_klass, class_name: 'Labimotion::SegmentKlass'
|
|
8
13
|
end
|
|
9
14
|
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.
|
|
4
|
+
version: 2.2.0.rc1
|
|
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-25 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: caxlsx
|
|
@@ -120,7 +120,9 @@ 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
|
|
125
|
+
- lib/labimotion/models/concerns/metadata_validation.rb
|
|
124
126
|
- lib/labimotion/models/concerns/segmentable.rb
|
|
125
127
|
- lib/labimotion/models/concerns/workflow.rb
|
|
126
128
|
- lib/labimotion/models/dataset.rb
|
|
@@ -145,6 +147,7 @@ files:
|
|
|
145
147
|
- lib/labimotion/models/segments_revision.rb
|
|
146
148
|
- lib/labimotion/models/std_layer.rb
|
|
147
149
|
- lib/labimotion/models/std_layers_revision.rb
|
|
150
|
+
- lib/labimotion/models/template_submission.rb
|
|
148
151
|
- lib/labimotion/models/vocabulary.rb
|
|
149
152
|
- lib/labimotion/models/wellplate.rb
|
|
150
153
|
- lib/labimotion/utils/con_state.rb
|