labimotion 2.3.0 → 2.4.0.rc11

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/lib/labimotion/apis/generic_dataset_api.rb +93 -3
  4. data/lib/labimotion/apis/generic_element_api.rb +198 -8
  5. data/lib/labimotion/apis/generic_klass_api.rb +74 -8
  6. data/lib/labimotion/apis/klass_share_api.rb +648 -0
  7. data/lib/labimotion/apis/labimotion_ai_api.rb +252 -0
  8. data/lib/labimotion/apis/labimotion_api.rb +4 -0
  9. data/lib/labimotion/apis/labimotion_doi_api.rb +24 -10
  10. data/lib/labimotion/apis/labimotion_template_browse_api.rb +13 -1
  11. data/lib/labimotion/apis/ontology_root_api.rb +74 -0
  12. data/lib/labimotion/apis/segment_api.rb +77 -10
  13. data/lib/labimotion/apis/user_klass_settings_api.rb +93 -0
  14. data/lib/labimotion/conf.rb +5 -0
  15. data/lib/labimotion/constants.rb +64 -0
  16. data/lib/labimotion/entities/application_entity.rb +8 -0
  17. data/lib/labimotion/entities/eln_element_entity.rb +6 -0
  18. data/lib/labimotion/entities/generic_klass_entity.rb +126 -0
  19. data/lib/labimotion/entities/klass_share_entity.rb +48 -0
  20. data/lib/labimotion/entities/properties_entity.rb +78 -2
  21. data/lib/labimotion/entities/segment_entity.rb +8 -0
  22. data/lib/labimotion/entities/user_klass_setting_entity.rb +10 -0
  23. data/lib/labimotion/helpers/cover_image_helpers.rb +181 -0
  24. data/lib/labimotion/helpers/dataset_helpers.rb +187 -1
  25. data/lib/labimotion/helpers/element_helpers.rb +282 -6
  26. data/lib/labimotion/helpers/exporter_helpers.rb +17 -2
  27. data/lib/labimotion/helpers/generic_helpers.rb +293 -4
  28. data/lib/labimotion/helpers/param_helpers.rb +105 -0
  29. data/lib/labimotion/helpers/sample_association_helpers.rb +7 -0
  30. data/lib/labimotion/helpers/segment_helpers.rb +102 -4
  31. data/lib/labimotion/libs/ai_egress_guard.rb +99 -0
  32. data/lib/labimotion/libs/ai_klass_queue.rb +88 -0
  33. data/lib/labimotion/libs/ai_klass_validator.rb +74 -0
  34. data/lib/labimotion/libs/ai_models.rb +201 -0
  35. data/lib/labimotion/libs/ai_template.rb +2285 -0
  36. data/lib/labimotion/libs/converter.rb +5 -43
  37. data/lib/labimotion/libs/data/datacite/labimotion_template.html.erb +67 -0
  38. data/lib/labimotion/libs/export_element.rb +128 -13
  39. data/lib/labimotion/libs/file_extractor.rb +210 -0
  40. data/lib/labimotion/libs/linked_element.rb +313 -0
  41. data/lib/labimotion/libs/ontology_store.rb +226 -0
  42. data/lib/labimotion/libs/ontology_terms.rb +227 -0
  43. data/lib/labimotion/libs/owner_resolver.rb +50 -0
  44. data/lib/labimotion/libs/ownership_audit.rb +73 -0
  45. data/lib/labimotion/libs/sample_association.rb +52 -1
  46. data/lib/labimotion/libs/share_notifier.rb +114 -0
  47. data/lib/labimotion/libs/share_resolver.rb +373 -0
  48. data/lib/labimotion/libs/user_ai_settings.rb +129 -0
  49. data/lib/labimotion/models/cellline.rb +47 -0
  50. data/lib/labimotion/models/concerns/datasetable.rb +3 -0
  51. data/lib/labimotion/models/concerns/matrice_labimotion.rb +124 -0
  52. data/lib/labimotion/models/concerns/segmentable.rb +2 -0
  53. data/lib/labimotion/models/concerns/template_doi.rb +133 -0
  54. data/lib/labimotion/models/dataset_klass.rb +1 -1
  55. data/lib/labimotion/models/element_klass.rb +1 -1
  56. data/lib/labimotion/models/klass_share.rb +129 -0
  57. data/lib/labimotion/models/segment_klass.rb +1 -1
  58. data/lib/labimotion/models/user_klass_setting.rb +58 -0
  59. data/lib/labimotion/models/user_setting.rb +60 -0
  60. data/lib/labimotion/usecases/build_template_doi_xml.rb +69 -23
  61. data/lib/labimotion/usecases/release_template_doi.rb +42 -17
  62. data/lib/labimotion/usecases/template_doi_helpers.rb +28 -6
  63. data/lib/labimotion/usecases/update_template_publication_metadata.rb +71 -2
  64. data/lib/labimotion/utils/export_utils.rb +1 -0
  65. data/lib/labimotion/utils/import_utils.rb +20 -3
  66. data/lib/labimotion/utils/serializer.rb +27 -0
  67. data/lib/labimotion/utils/units.rb +32 -67
  68. data/lib/labimotion/version.rb +1 -1
  69. data/lib/labimotion.rb +27 -0
  70. metadata +45 -3
@@ -15,11 +15,29 @@ module Labimotion
15
15
  # admin rights over it. Keys are plural, matching the LabIMotion gem's
16
16
  # `authenticate_admin!` and `User#generic_admin`.
17
17
  GENERIC_ADMIN_KEY = {
18
- ::Labimotion::ElementKlass => 'elements',
19
- ::Labimotion::SegmentKlass => 'segments',
20
- ::Labimotion::DatasetKlass => 'datasets'
18
+ ::Labimotion::ElementKlass => ::Labimotion::Constants::Family::ELEMENT,
19
+ ::Labimotion::SegmentKlass => ::Labimotion::Constants::Family::SEGMENT,
20
+ ::Labimotion::DatasetKlass => ::Labimotion::Constants::Family::DATASET
21
21
  }.freeze
22
22
 
23
+ # Where the hub lives, most specific first. PUBLIC_URL is the instance's own
24
+ # public address (the host app's config/application.rb insists on it), so the
25
+ # link follows whichever instance is serving it rather than a hardcoded
26
+ # chemotion-repository.net. The DataCite-facing domains stay as fallbacks for
27
+ # deployments that only set those.
28
+ HOST_ENV_KEYS = %w[PUBLIC_URL REPO_HOST DOI_DOMAIN_TEST DOI_DOMAIN].freeze
29
+
30
+ # The DataCite kernel-4 contributorType vocabulary. A template DOI may name
31
+ # any number of contributors — including none — each credited in one of
32
+ # these roles. The list is closed: DataCite rejects anything else.
33
+ CONTRIBUTOR_TYPES = %w[
34
+ ContactPerson DataCollector DataCurator DataManager Distributor Editor
35
+ HostingInstitution Producer ProjectLeader ProjectManager ProjectMember
36
+ RegistrationAgency RegistrationAuthority RelatedPerson Researcher
37
+ ResearchGroup RightsHolder Sponsor Supervisor WorkPackageLeader Other
38
+ ].freeze
39
+ DEFAULT_CONTRIBUTOR_TYPE = 'Researcher'
40
+
23
41
  module_function
24
42
 
25
43
  # True once the template's latest DOI has been released (minted) and the
@@ -49,13 +67,17 @@ module Labimotion
49
67
  # Used as the DOI's DataCite landing page and surfaced in the UI.
50
68
  def template_url(record)
51
69
  type = klass_type_for(record)
52
- host = ENV['REPO_HOST'].presence || ENV['DOI_DOMAIN_TEST'].presence ||
53
- ENV['DOI_DOMAIN'].presence || 'https://www.chemotion-repository.net'
54
70
  record_id = record.try(:identifier).presence || record.try(:uuid).presence || record.id
55
71
  query = "type=finder&kind=#{type}&id=#{record_id}"
56
72
  version = record.try(:version)
57
73
  query += "&version=#{version}" if version.present?
58
- "#{host.chomp('/')}/home/genericHub?#{query}"
74
+ "#{public_host}/home/genericHub?#{query}"
75
+ end
76
+
77
+ # The instance serving the hub, without its trailing slash.
78
+ def public_host
79
+ host = HOST_ENV_KEYS.lazy.filter_map { |key| ENV[key].presence }.first
80
+ (host || 'http://localhost:3000').chomp('/')
59
81
  end
60
82
 
61
83
  # A user may manage a template's DOI iff they hold the LabIMotion
@@ -7,7 +7,12 @@ module Labimotion
7
7
  class UpdateTemplatePublicationMetadata
8
8
  include TemplateDoiHelpers
9
9
 
10
- ALLOWED_KEYS = %w[title description authors license].freeze
10
+ ALLOWED_KEYS = %w[title description authors contributors references license].freeze
11
+ REFERENCE_KEYS = %w[doi title url].freeze
12
+ # Authors and contributors are the same shape: a DataCite personal name plus
13
+ # the identifiers that make it resolvable — ORCID for the person, ROR for
14
+ # their organisation. Contributors carry a contributorType on top.
15
+ PERSON_KEYS = %w[givenName familyName orcid affiliation affiliation_id ror_id].freeze
11
16
 
12
17
  attr_reader :record, :current_user, :publication, :error
13
18
 
@@ -39,18 +44,82 @@ module Labimotion
39
44
  def normalized_publication
40
45
  slice = publication.stringify_keys.slice(*ALLOWED_KEYS)
41
46
  slice['authors'] = Array(slice['authors']).filter_map { |a| normalize_author(a) }
47
+ # Contributors are people in their own right — none of them need be one of
48
+ # the authors — so they are stored as given rather than matched back
49
+ # against the author list. There may be any number, including none.
50
+ slice['contributors'] = submitted_contributors.filter_map { |c| normalize_contributor(c) }
51
+ slice['references'] = Array(slice['references']).filter_map { |r| normalize_reference(r) }
42
52
  slice
43
53
  end
44
54
 
55
+ # A single `contributor` is what the first version of the form sent; a
56
+ # template saved by it is read back into the list rather than dropped.
57
+ def submitted_contributors
58
+ given = publication.stringify_keys
59
+ given['contributors'].is_a?(Array) ? given['contributors'] : [given['contributor']].compact
60
+ end
61
+
62
+ # A person plus the DataCite role they are credited in. An unknown or
63
+ # missing role falls back to "Researcher" rather than failing the save —
64
+ # the vocabulary is closed, so anything else would be rejected at minting.
65
+ def normalize_contributor(contributor)
66
+ h = normalize_author(contributor)
67
+ return nil unless h
68
+
69
+ type = contributor.stringify_keys['contributorType'].to_s.strip
70
+ known = TemplateDoiHelpers::CONTRIBUTOR_TYPES.include?(type)
71
+ h.merge('contributorType' => known ? type : TemplateDoiHelpers::DEFAULT_CONTRIBUTOR_TYPE)
72
+ end
73
+
74
+ # A cited work, identified by its DOI. Anything without one is dropped: the
75
+ # DOI is what goes to DataCite as a relatedIdentifier, and a reference
76
+ # without it would be published as an empty relation.
77
+ def normalize_reference(reference)
78
+ return nil unless reference.is_a?(Hash)
79
+
80
+ h = reference.stringify_keys.slice(*REFERENCE_KEYS)
81
+ h['doi'] = sanitize_doi(h['doi'])
82
+ return nil if h['doi'].nil?
83
+
84
+ h.transform_values { |v| v.to_s.strip }
85
+ end
86
+
87
+ # Accepts a bare DOI, a doi: prefix or a resolver URL, and keeps the bare
88
+ # "10.x/y" form. Nil for anything that is not a DOI.
89
+ def sanitize_doi(value)
90
+ match = value.to_s.strip.match(%r{(10\.\d{4,9}/\S+)\z})
91
+ match && match[1]
92
+ end
93
+
45
94
  def normalize_author(author)
46
95
  return nil unless author.is_a?(Hash)
47
96
 
48
- h = author.stringify_keys.slice('givenName', 'familyName', 'orcid', 'affiliation', 'affiliation_id')
97
+ h = author.stringify_keys.slice(*PERSON_KEYS)
49
98
  return nil if h.values_at('givenName', 'familyName').all? { |v| v.to_s.strip.empty? }
50
99
 
100
+ ror = normalize_ror(h['ror_id']) || ror_for(h['affiliation_id'])
101
+ ror ? h['ror_id'] = ror : h.delete('ror_id')
51
102
  h
52
103
  end
53
104
 
105
+ # ROR IDs travel either bare ("05f950310") or as a resolver URL; DataCite
106
+ # wants the URI, so the bare form is what gets stored and the URI is built
107
+ # when the XML is rendered.
108
+ def normalize_ror(value)
109
+ value.to_s.strip.sub(%r{\Ahttps?://ror\.org/}i, '').presence
110
+ end
111
+
112
+ # The authoritative ROR for a picked affiliation. Whoever the editor picked
113
+ # came from an Affiliation record, so its id is the better source than
114
+ # anything retyped — and the current-user payload carries no ROR at all.
115
+ def ror_for(affiliation_id)
116
+ return nil if affiliation_id.blank? || !defined?(::Affiliation)
117
+
118
+ normalize_ror(::Affiliation.where(id: affiliation_id).pick(:ror_id))
119
+ rescue StandardError
120
+ nil
121
+ end
122
+
54
123
  def failure(message)
55
124
  @error = message
56
125
  self
@@ -156,6 +156,7 @@ module Labimotion
156
156
 
157
157
  set_table_prop(field, uuids, Labimotion::FieldType::DRAG_MOLECULE, &fetch_one)
158
158
  set_table_prop(field, uuids, Labimotion::FieldType::DRAG_SAMPLE, &fetch_one)
159
+ set_table_prop(field, uuids, Labimotion::FieldType::DRAG_ELEMENT, &fetch_one)
159
160
  end
160
161
  properties
161
162
  rescue StandardError => e
@@ -120,7 +120,21 @@ module Labimotion
120
120
  properties
121
121
  end
122
122
 
123
- def proc_table_prop(layer, key, data, instance, properties, field, tidx, type)
123
+ def proc_table_element(properties, instances, elements, svalue, key, tidx, vdx, col_id)
124
+ return properties unless id = svalue.fetch('el_id', nil)
125
+
126
+ att_el = (elements && elements[id]) || instances.fetch(Labimotion::Prop::L_ELEMENT, nil)&.fetch(id, nil)
127
+ return properties if att_el.nil?
128
+
129
+ val = properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][tidx]['sub_values'][vdx][col_id]['value']
130
+ properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][tidx]['sub_values'][vdx][col_id]['value'] = proc_assign_element(val, att_el)
131
+ properties
132
+ rescue StandardError => e
133
+ Labimotion.log_exception(e)
134
+ properties
135
+ end
136
+
137
+ def proc_table_prop(layer, key, data, instance, properties, field, tidx, type, elements = nil)
124
138
  fields = field[Labimotion::Prop::SUBFIELDS].select { |ss| ss['type'] == type }
125
139
  return properties if fields.nil?
126
140
 
@@ -141,6 +155,8 @@ module Labimotion
141
155
  properties = proc_table_molecule(properties, data, svalue, key, tidx, vdx, col_id)
142
156
  when Labimotion::FieldType::DRAG_SAMPLE
143
157
  properties = proc_table_sample(properties, data, instance, svalue, key, tidx, vdx, col_id)
158
+ when Labimotion::FieldType::DRAG_ELEMENT
159
+ properties = proc_table_element(properties, instance, elements, svalue, key, tidx, vdx, col_id)
144
160
  end
145
161
  end
146
162
  end
@@ -256,7 +272,7 @@ module Labimotion
256
272
  end
257
273
 
258
274
 
259
- def self.proc_table(layer, key, data, instance, properties)
275
+ def self.proc_table(layer, key, data, instance, properties, elements = nil)
260
276
  fields = layer[Labimotion::Prop::FIELDS].select { |ss| ss['type'] == Labimotion::FieldType::TABLE }
261
277
  fields&.each do |field|
262
278
  tidx = layer[Labimotion::Prop::FIELDS].index(field)
@@ -264,6 +280,7 @@ module Labimotion
264
280
 
265
281
  proc_table_prop(layer, key, data, instance, properties, field, tidx, Labimotion::FieldType::DRAG_MOLECULE)
266
282
  proc_table_prop(layer, key, data, instance, properties, field, tidx, Labimotion::FieldType::DRAG_SAMPLE)
283
+ proc_table_prop(layer, key, data, instance, properties, field, tidx, Labimotion::FieldType::DRAG_ELEMENT, elements)
267
284
  end
268
285
  properties
269
286
  rescue StandardError => e
@@ -280,7 +297,7 @@ module Labimotion
280
297
  properties = proc_reaction(layer, key, data, instances, properties)
281
298
  properties = proc_sample(layer, key, data, instances, properties)
282
299
  properties = proc_element(layer, key, data, instances, properties, elements) # unless elements.nil?
283
- properties = proc_table(layer, key, data, instances, properties)
300
+ properties = proc_table(layer, key, data, instances, properties, elements)
284
301
  end
285
302
  properties
286
303
  rescue StandardError => e
@@ -32,6 +32,30 @@ module Labimotion
32
32
  field
33
33
  end
34
34
 
35
+ ## Refresh the stored label/name of every drag_element cell of a table field.
36
+ ## Shared by PropertiesEntity and ElnElementEntity so all three loaders agree.
37
+ def self.set_table_element(field, field_table_elements)
38
+ col_ids = field_table_elements.map { |x| x.values[0] }
39
+ col_ids.each do |col_id|
40
+ field['sub_values'].each do |sub_value|
41
+ cell = sub_value[col_id]
42
+ next unless cell.present? && cell['value'].present? && cell['value']['el_id'].present?
43
+ ## A drag_element cell may link a standard ELN element (reaction, wellplate, ...);
44
+ ## el_id is then not a Labimotion::Element id, so keep what the client stored.
45
+ next if Labimotion::LinkedElement::MODELS.key?(cell['value']['el_klass'].to_s)
46
+
47
+ find_obj = Labimotion::Element.find_by(id: cell['value']['el_id'])
48
+ next if find_obj.blank?
49
+
50
+ cell['value']['el_label'] = find_obj.short_label
51
+ cell['value']['el_name'] = find_obj.name
52
+ cell['value']['el_tip'] = "#{find_obj.element_klass&.label}@@#{find_obj.name}"
53
+ cell['value']['icon_name'] = find_obj.element_klass&.icon_name || ''
54
+ end
55
+ end
56
+ field
57
+ end
58
+
35
59
  def self.element_properties(object)
36
60
  object.properties[Labimotion::Prop::LAYERS]&.keys.each do |key|
37
61
  # layer = object.properties[key]
@@ -72,6 +96,9 @@ module Labimotion
72
96
 
73
97
  field_table_samples = field[Labimotion::Prop::SUBFIELDS].select { |ss| ss['type'] == Labimotion::FieldType::DRAG_SAMPLE }
74
98
  object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx] = set_table(field, field_table_samples, Labimotion::Prop::SAMPLE) if field_table_samples.present?
99
+
100
+ field_table_elements = field[Labimotion::Prop::SUBFIELDS].select { |ss| ss['type'] == Labimotion::FieldType::DRAG_ELEMENT }
101
+ object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx] = set_table_element(field, field_table_elements) if field_table_elements.present?
75
102
  end
76
103
  end
77
104
  object.properties
@@ -9,7 +9,7 @@ module Labimotion
9
9
  "default": "",
10
10
  "position": 10,
11
11
  "placeholder": "acceleration",
12
- "units": [{ "key": "mm_s2", "label": "mm/s²" }]
12
+ "units": [{ "key": "mm_s2", "label": "mm/s<sup>2</sup>" }]
13
13
  },
14
14
  {
15
15
  "type": "numeric",
@@ -59,10 +59,10 @@ module Labimotion
59
59
  "position": 38,
60
60
  "placeholder": "areal density",
61
61
  "units": [
62
- { "key": "kg_m2", "label": "kg m⁻²", "nm": 1 },
63
- { "key": "t_m2", "label": "t m⁻²", "nm": 0.001 },
64
- { "key": "kg_cm2", "label": "kg cm⁻²", "nm": 1e-4 },
65
- { "key": "g_m2", "label": "g m⁻²", "nm": 1000 }
62
+ { "key": "kg_m2", "label": "kg m<sup>-2</sup>", "nm": 1 },
63
+ { "key": "t_m2", "label": "t m<sup>-2</sup>", "nm": 0.001 },
64
+ { "key": "kg_cm2", "label": "kg cm<sup>-2</sup>", "nm": 1e-4 },
65
+ { "key": "g_m2", "label": "g m<sup>-2</sup>", "nm": 1000 }
66
66
  ]
67
67
  },
68
68
  {
@@ -97,7 +97,7 @@ module Labimotion
97
97
  "position": 60,
98
98
  "placeholder": "concentration",
99
99
  "units": [
100
- { "key": "ng_l", "label": "ng/L", "nm": 1000000000 },
100
+ { "key": "ng_l", "label": "ng/L", "nm": 1000000 },
101
101
  { "key": "mg_l", "label": "mg/L", "nm": 1000 },
102
102
  { "key": "g_l", "label": "g/L", "nm": 1 }
103
103
  ]
@@ -171,7 +171,7 @@ module Labimotion
171
171
  "position": 75,
172
172
  "placeholder": "density",
173
173
  "units": [
174
- { "key": "g_cm3", "label": "g/cm³", "nm": 1 },
174
+ { "key": "g_cm3", "label": "g/cm<sup>3</sup>", "nm": 1 },
175
175
  { "key": "kg_l", "label": "kg/l", "nm": 1 }
176
176
  ]
177
177
  },
@@ -198,8 +198,7 @@ module Labimotion
198
198
  { "key": "d", "label": "d", "nm": 1 },
199
199
  { "key": "h", "label": "h", "nm": 24 },
200
200
  { "key": "min", "label": "m", "nm": 1440 },
201
- { "key": "s", "label": "s", "nm": 86400 },
202
- { "key": "y", "label": "y", "nm": 0.0027378507871321013 }
201
+ { "key": "s", "label": "s", "nm": 86400 }
203
202
  ]
204
203
  },
205
204
  {
@@ -281,8 +280,7 @@ module Labimotion
281
280
  { "key": "eV", "label": "eV", "nm": 6.241509e21 },
282
281
  { "key": "keV", "label": "keV", "nm": 6.241509e18 },
283
282
  { "key": "j", "label": "J", "nm": 1000 },
284
- { "key": "k_j", "label": "kJ", "nm": 1 },
285
- { "key": "kWh", "label": "kWh", "nm": 2.7777778e-4 }
283
+ { "key": "k_j", "label": "kJ", "nm": 1 }
286
284
  ]
287
285
  },
288
286
  {
@@ -359,9 +357,9 @@ module Labimotion
359
357
  { "key": "k_min", "label": "K/min", "nm": 1 },
360
358
  { "key": "k_s", "label": "K/s", "nm": 0.016666666666667 },
361
359
  { "key": "k_h", "label": "K/h", "nm": 60 },
362
- { "key": "degc_min", "label": "°C min⁻¹", "nm": 1 },
363
- { "key": "degc_s", "label": "°C s⁻¹", "nm": 0.016666666666667 },
364
- { "key": "degc_h", "label": "°C h⁻¹", "nm": 60 }
360
+ { "key": "degc_min", "label": "°C min<sup>-1</sup>", "nm": 1 },
361
+ { "key": "degc_s", "label": "°C s<sup>-1</sup>", "nm": 0.016666666666667 },
362
+ { "key": "degc_h", "label": "°C h<sup>-1</sup>", "nm": 60 }
365
363
  ]
366
364
  },
367
365
  {
@@ -396,23 +394,7 @@ module Labimotion
396
394
  "units": [
397
395
  { "key": "g", "label": "g", "nm": 1 },
398
396
  { "key": "mg", "label": "mg", "nm": 1000 },
399
- { "key": "ug", "label": "µg", "nm": 1000000 },
400
- { "key": "kg", "label": "kg", "nm": 0.001 }
401
- ]
402
- },
403
- {
404
- "type": "numeric",
405
- "field": "mass_flow",
406
- "label": "Mass flow",
407
- "default": "",
408
- "position": 121,
409
- "placeholder": "mass flow",
410
- "units": [
411
- { "key": "g_min", "label": "g/min", "nm": 1 },
412
- { "key": "kg_h", "label": "kg/h", "nm": 0.06 },
413
- { "key": "kg_s", "label": "kg/s", "nm": 0.000016666666666667 },
414
- { "key": "g_s", "label": "g/s", "nm": 0.016666666666667 },
415
- { "key": "mg_s", "label": "mg/s", "nm": 16.666666666667 }
397
+ { "key": "ug", "label": "µg", "nm": 1000000 }
416
398
  ]
417
399
  },
418
400
  {
@@ -434,8 +416,8 @@ module Labimotion
434
416
  "position": 125,
435
417
  "placeholder": "mass loading",
436
418
  "units": [
437
- { "key": "g_cm2", "label": "g cm⁻²", "nm": 1 },
438
- { "key": "mg_cm2", "label": "mg cm⁻²", "nm": 1000 }
419
+ { "key": "g_cm2", "label": "g cm<sup>-2</sup>", "nm": 1 },
420
+ { "key": "mg_cm2", "label": "mg cm<sup>-2</sup>", "nm": 1000 }
439
421
  ]
440
422
  },
441
423
  {
@@ -458,7 +440,7 @@ module Labimotion
458
440
  "position": 127,
459
441
  "placeholder": "molar conductivity",
460
442
  "units": [
461
- { "key": "s_cm2_mol", "label": "S cm² mol⁻¹", "nm": 1 }
443
+ { "key": "s_cm2_mol", "label": "S cm<sup>2</sup> mol<sup>-1</sup>", "nm": 1 }
462
444
  ]
463
445
  },
464
446
  {
@@ -510,7 +492,6 @@ module Labimotion
510
492
  { "key": "atm", "label": "atm", "nm": 1 },
511
493
  { "key": "pa", "label": "Pa", "nm": 101325 },
512
494
  { "key": "kpa", "label": "kPa", "nm": 101.325 },
513
- { "key": "mpa", "label": "MPa", "nm": 0.101325 },
514
495
  { "key": "hpa", "label": "hPa", "nm": 1013.25 },
515
496
  { "key": "torr", "label": "Torr", "nm": 760 },
516
497
  { "key": "bar", "label": "bar", "nm": 1.01325 },
@@ -549,8 +530,8 @@ module Labimotion
549
530
  "position": 150,
550
531
  "placeholder": "Reaction rate",
551
532
  "units": [
552
- { "key": "mol_lmin", "label": "mol L⁻¹ min⁻¹", "nm": 1 },
553
- { "key": "mol_lsec", "label": "mol L⁻¹ s⁻¹", "nm": 0.016666666666667 }
533
+ { "key": "mol_lmin", "label": "mol L<sup>-1</sup> min<sup>-1</sup>", "nm": 1 },
534
+ { "key": "mol_lsec", "label": "mol L<sup>-1</sup> s<sup>-1</sup>", "nm": 0.016666666666667 }
554
535
  ]
555
536
  },
556
537
  {
@@ -577,22 +558,6 @@ module Labimotion
577
558
  { "key": "v_s", "label": "V/s", "nm": 1 }
578
559
  ]
579
560
  },
580
- {
581
- "type": "numeric",
582
- "field": "space_time_yield",
583
- "label": "Space-time yield",
584
- "default": "",
585
- "position": 156,
586
- "placeholder": "space-time yield",
587
- "units": [
588
- { "key": "kg_m3_d", "label": "kg/(m³*d)", "nm": 1 },
589
- { "key": "kg_m3_h", "label": "kg/(m³*h)", "nm": 0.041666666666667 },
590
- { "key": "g_l_h", "label": "g/(L*h)", "nm": 0.041666666666667 },
591
- { "key": "mg_ml_h", "label": "mg/(mL*h)", "nm": 0.041666666666667 },
592
- { "key": "g_l_min", "label": "g/(L*min)", "nm": 0.00069444444444444 },
593
- { "key": "g_m3_s", "label": "g/(m³*s)", "nm": 0.011574074074074 }
594
- ]
595
- },
596
561
  {
597
562
  "type": "numeric",
598
563
  "field": "specific_current",
@@ -603,9 +568,9 @@ module Labimotion
603
568
  "units": [
604
569
  { "key": "ma_g", "label": "mA/g", "nm": 1000, "unit_type": "mass" },
605
570
  { "key": "a_g", "label": "A/g", "nm": 1, "unit_type": "mass" },
606
- { "key": "ma_cm2", "label": "mA/cm²", "nm": 1000, "unit_type": "area" },
607
- { "key": "a_cm2", "label": "A/cm²", "nm": 1, "unit_type": "area" },
608
- { "key": "a_mm2", "label": "A/mm²", "nm": 0.01, "unit_type": "area" }
571
+ { "key": "ma_cm2", "label": "mA/cm<sup>2</sup>", "nm": 1000, "unit_type": "area" },
572
+ { "key": "a_cm2", "label": "A/cm<sup>2</sup>", "nm": 1, "unit_type": "area" },
573
+ { "key": "a_mm2", "label": "A/mm<sup>2</sup>", "nm": 0.01, "unit_type": "area" }
609
574
  ]
610
575
  },
611
576
  {
@@ -628,7 +593,7 @@ module Labimotion
628
593
  "position": 158,
629
594
  "placeholder": "Specific surface area",
630
595
  "units": [
631
- { "key": "m2_g", "label": "m²/g", "nm": 1 }
596
+ { "key": "m2_g", "label": "m<sup>2</sup>/g", "nm": 1 }
632
597
  ]
633
598
  },
634
599
  {
@@ -638,7 +603,7 @@ module Labimotion
638
603
  "default": "",
639
604
  "position": 160,
640
605
  "placeholder": "Specific Volume",
641
- "units": [{ "key": "cm3_g", "label": "cm³/g", "nm": 1 }]
606
+ "units": [{ "key": "cm3_g", "label": "cm<sup>3</sup>/g", "nm": 1 }]
642
607
  },
643
608
  {
644
609
  "type": "numeric",
@@ -677,10 +642,10 @@ module Labimotion
677
642
  "position": 170,
678
643
  "placeholder": "surface",
679
644
  "units": [
680
- { "key": "a_2", "label": "A²", "nm": 1.0e16 },
681
- { "key": "um_2", "label": "µm²", "nm": 1.0e8 },
682
- { "key": "mm_2", "label": "mm²", "nm": 100 },
683
- { "key": "cm_2", "label": "cm²", "nm": 1 }
645
+ { "key": "a_2", "label": "A<sup>2</sup>", "nm": 1.0e16 },
646
+ { "key": "um_2", "label": "µm<sup>2</sup>", "nm": 1.0e8 },
647
+ { "key": "mm_2", "label": "mm<sup>2</sup>", "nm": 100 },
648
+ { "key": "cm_2", "label": "cm<sup>2</sup>", "nm": 1 }
684
649
  ]
685
650
  },
686
651
  {
@@ -717,8 +682,8 @@ module Labimotion
717
682
  "position": 186,
718
683
  "placeholder": "tensile stress",
719
684
  "units": [
720
- { "key": "n_cm2", "label": "N cm⁻²", "nm": 1 },
721
- { "key": "n_mm2", "label": "N mm⁻²", "nm": 0.01 }
685
+ { "key": "n_cm2", "label": "N cm<sup>-2</sup>", "nm": 1 },
686
+ { "key": "n_mm2", "label": "N mm<sup>-2</sup>", "nm": 0.01 }
722
687
  ]
723
688
  },
724
689
  {
@@ -728,7 +693,7 @@ module Labimotion
728
693
  "default": "",
729
694
  "position": 190,
730
695
  "placeholder": "Turnover number",
731
- "units": [{ "key": "1_s", "label": "1/s", "nm": 1 }, { "key": "1_m", "label": "1/min", "nm": 60 }]
696
+ "units": [{ "key": "1_s", "label": "1/s", "nm": 1 }, { "key": "1_m", "label": "1/m", "nm": 60 }]
732
697
  },
733
698
  {
734
699
  "type": "numeric",
@@ -749,7 +714,7 @@ module Labimotion
749
714
  "default": "",
750
715
  "position": 205,
751
716
  "placeholder": "Kinematic Viscosity",
752
- "units": [{ "key": "m2_s", "label": "m²/s", "nm": 1 }]
717
+ "units": [{ "key": "m2_s", "label": "m<sup>2</sup>/s", "nm": 1 }]
753
718
  },
754
719
  {
755
720
  "type": "numeric",
@@ -802,6 +767,6 @@ module Labimotion
802
767
  { "key": "m3", "label": "m³", "nm": 0.000001 }
803
768
  ]
804
769
  }
805
- ]
770
+ ]
806
771
  end
807
772
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  ## Labimotion Version
4
4
  module Labimotion
5
- VERSION = '2.3.0'
5
+ VERSION = '2.4.0.rc11'
6
6
  end
data/lib/labimotion.rb CHANGED
@@ -27,7 +27,11 @@ module Labimotion
27
27
  autoload :ExporterAPI, 'labimotion/apis/exporter_api'
28
28
  autoload :StandardLayerAPI, 'labimotion/apis/standard_layer_api'
29
29
  autoload :VocabularyAPI, 'labimotion/apis/vocabulary_api'
30
+ autoload :OntologyRootAPI, 'labimotion/apis/ontology_root_api'
30
31
  autoload :UserAPI, 'labimotion/apis/user_api'
32
+ autoload :LabimotionAiAPI, 'labimotion/apis/labimotion_ai_api'
33
+ autoload :UserKlassSettingsAPI, 'labimotion/apis/user_klass_settings_api'
34
+ autoload :KlassShareAPI, 'labimotion/apis/klass_share_api'
31
35
  autoload :MttAPI, 'labimotion/apis/mtt_api'
32
36
  autoload :ElementVariationAPI, 'labimotion/apis/element_variation_api'
33
37
  autoload :LabimotionDoiAPI, 'labimotion/apis/labimotion_doi_api'
@@ -56,12 +60,15 @@ module Labimotion
56
60
  ## autoload :DatasetRevisionEntity, 'labimotion/entities/dataset_revision_entity'
57
61
  autoload :VocabularyEntity, 'labimotion/entities/vocabulary_entity'
58
62
  autoload :UserEntity, 'labimotion/entities/user_entity'
63
+ autoload :UserKlassSettingEntity, 'labimotion/entities/user_klass_setting_entity'
64
+ autoload :KlassShareEntity, 'labimotion/entities/klass_share_entity'
59
65
  autoload :ElementVariationEntity, 'labimotion/entities/element_variation_entity'
60
66
  autoload :LabimotionTemplateDoiEntity, 'labimotion/entities/labimotion_template_doi_entity'
61
67
 
62
68
  ######## Helpers
63
69
  autoload :GenericHelpers, 'labimotion/helpers/generic_helpers'
64
70
  autoload :ElementHelpers, 'labimotion/helpers/element_helpers'
71
+ autoload :CoverImageHelpers, 'labimotion/helpers/cover_image_helpers'
65
72
  autoload :SegmentHelpers, 'labimotion/helpers/segment_helpers'
66
73
  autoload :DatasetHelpers, 'labimotion/helpers/dataset_helpers'
67
74
  autoload :SearchHelpers, 'labimotion/helpers/search_helpers'
@@ -80,6 +87,15 @@ module Labimotion
80
87
  autoload :UpdateTemplatePublicationMetadata, 'labimotion/usecases/update_template_publication_metadata'
81
88
 
82
89
  ######## Libs
90
+ autoload :AiTemplate, 'labimotion/libs/ai_template'
91
+ autoload :AiKlassQueue, 'labimotion/libs/ai_klass_queue'
92
+ autoload :AiKlassValidator, 'labimotion/libs/ai_klass_validator'
93
+ autoload :AiEgressGuard, 'labimotion/libs/ai_egress_guard'
94
+ autoload :AiModels, 'labimotion/libs/ai_models'
95
+ autoload :UserAiSettings, 'labimotion/libs/user_ai_settings'
96
+ autoload :OntologyTerms, 'labimotion/libs/ontology_terms'
97
+ autoload :OntologyStore, 'labimotion/libs/ontology_store'
98
+ autoload :FileExtractor, 'labimotion/libs/file_extractor'
83
99
  autoload :Converter, 'labimotion/libs/converter'
84
100
  autoload :DatasetBuilder, 'labimotion/libs/dataset_builder'
85
101
  autoload :NmrMapper, 'labimotion/libs/nmr_mapper'
@@ -89,6 +105,7 @@ module Labimotion
89
105
  autoload :ExportDataset, 'labimotion/libs/export_dataset'
90
106
  autoload :SampleAssociation, 'labimotion/libs/sample_association'
91
107
  autoload :PropertiesHandler, 'labimotion/libs/properties_handler'
108
+ autoload :LinkedElement, 'labimotion/libs/linked_element'
92
109
  autoload :AttachmentHandler, 'labimotion/libs/attachment_handler'
93
110
  autoload :VocabularyHandler, 'labimotion/libs/vocabulary_handler'
94
111
  autoload :XlsxExporter, 'labimotion/libs/xlsx_exporter'
@@ -96,6 +113,10 @@ module Labimotion
96
113
  autoload :ElementVariationHeader, 'labimotion/libs/element_variation_header'
97
114
  autoload :ExportElementVariations, 'labimotion/libs/export_element_variations'
98
115
  autoload :ImportElementVariations, 'labimotion/libs/import_element_variations'
116
+ autoload :OwnerResolver, 'labimotion/libs/owner_resolver'
117
+ autoload :OwnershipAudit, 'labimotion/libs/ownership_audit'
118
+ autoload :ShareNotifier, 'labimotion/libs/share_notifier'
119
+ autoload :ShareResolver, 'labimotion/libs/share_resolver'
99
120
 
100
121
  ######## Utils
101
122
  autoload :Prop, 'labimotion/utils/prop'
@@ -133,7 +154,11 @@ module Labimotion
133
154
 
134
155
  autoload :StdLayer, 'labimotion/models/std_layer'
135
156
  autoload :StdLayersRevision, 'labimotion/models/std_layers_revision'
157
+ autoload :UserKlassSetting, 'labimotion/models/user_klass_setting'
158
+ autoload :UserSetting, 'labimotion/models/user_setting'
159
+ autoload :KlassShare, 'labimotion/models/klass_share'
136
160
 
161
+ autoload :CellLine, 'labimotion/models/cellline'
137
162
  autoload :DeviceDescription, 'labimotion/models/device_description'
138
163
  autoload :DoseRespRequest, 'labimotion/models/dose_resp_request'
139
164
  autoload :DoseRespOutput, 'labimotion/models/dose_resp_output'
@@ -151,5 +176,7 @@ module Labimotion
151
176
  autoload :Segmentable, 'labimotion/models/concerns/segmentable'
152
177
  autoload :Datasetable, 'labimotion/models/concerns/datasetable'
153
178
  autoload :AttachmentConverter, 'labimotion/models/concerns/attachment_converter'
179
+ autoload :MatriceLabimotion, 'labimotion/models/concerns/matrice_labimotion'
154
180
  autoload :LinkedProperties, 'labimotion/models/concerns/linked_properties'
181
+ autoload :TemplateDoi, 'labimotion/models/concerns/template_doi'
155
182
  end