labimotion 2.1.0.rc14 → 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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/labimotion/apis/generic_element_api.rb +1 -0
  3. data/lib/labimotion/entities/dataset_entity.rb +1 -0
  4. data/lib/labimotion/entities/element_entity.rb +1 -0
  5. data/lib/labimotion/entities/element_revision_entity.rb +1 -1
  6. data/lib/labimotion/entities/generic_klass_entity.rb +1 -0
  7. data/lib/labimotion/entities/generic_public_entity.rb +1 -0
  8. data/lib/labimotion/entities/klass_revision_entity.rb +1 -0
  9. data/lib/labimotion/entities/segment_entity.rb +1 -0
  10. data/lib/labimotion/entities/segment_revision_entity.rb +1 -1
  11. data/lib/labimotion/helpers/dataset_helpers.rb +1 -1
  12. data/lib/labimotion/helpers/element_helpers.rb +2 -1
  13. data/lib/labimotion/helpers/generic_helpers.rb +1 -0
  14. data/lib/labimotion/helpers/param_helpers.rb +2 -0
  15. data/lib/labimotion/helpers/segment_helpers.rb +1 -1
  16. data/lib/labimotion/models/concerns/datasetable.rb +8 -5
  17. data/lib/labimotion/models/concerns/generic_klass_revisions.rb +2 -1
  18. data/lib/labimotion/models/concerns/generic_revisions.rb +2 -1
  19. data/lib/labimotion/models/concerns/metadata_validation.rb +34 -0
  20. data/lib/labimotion/models/concerns/segmentable.rb +2 -2
  21. data/lib/labimotion/models/dataset_klass.rb +2 -0
  22. data/lib/labimotion/models/dataset_klasses_revision.rb +2 -0
  23. data/lib/labimotion/models/element_klass.rb +2 -0
  24. data/lib/labimotion/models/element_klasses_revision.rb +2 -0
  25. data/lib/labimotion/models/segment_klass.rb +2 -0
  26. data/lib/labimotion/models/segment_klasses_revision.rb +2 -0
  27. data/lib/labimotion/version.rb +1 -1
  28. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3be4d822cf9ab027e3d64f1b6356f02a6d696a6125c0db56bf8ca61e342eaabe
4
- data.tar.gz: 8038b4423f9c7a26fa01c07defd715809d4698a51b6362948de4560870ab4c61
3
+ metadata.gz: 4397eed28e8f2c6f0e21e022191d842dbb7a42000a2efe72731a89ab8bf9e77b
4
+ data.tar.gz: 3ae429541da0f787d6d0f544307b5acfbf3e922d83c7fc7cd27e47738eb5880e
5
5
  SHA512:
6
- metadata.gz: 3c2fe973a0fd5593246206ac697d84ae77bea51f32d1501d3fbd4dc79273d67d9ac04c54866c1cf2a952424043a1edca73591756cd5644c8156d07943bc51208
7
- data.tar.gz: 70b348d0130ee3fe9cc72e829013b06357172a16f5cda79e4799dcd019d317f2561ce2910e457382904cda7fe02d36465ef58fbde0de24803990fd0b428ea5c6
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
@@ -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
@@ -16,6 +16,7 @@ module Labimotion
16
16
  expose! :name
17
17
  expose! :properties
18
18
  expose! :properties_release
19
+ expose! :metadata
19
20
  expose! :short_label
20
21
  expose! :thumb_svg
21
22
  expose! :type
@@ -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 }
@@ -5,6 +5,7 @@ module Labimotion
5
5
  class KlassRevisionEntity < Labimotion::ApplicationEntity
6
6
  expose :id, :uuid, :version, :released_at, :klass_id, :submitted
7
7
  expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
8
+ expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
8
9
 
9
10
  def klass_id
10
11
  object.klass&.id
@@ -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
@@ -32,26 +32,29 @@ module Labimotion
32
32
  )
33
33
  end
34
34
 
35
- def save_dataset(**args)
35
+ def save_dataset(**dataset_args)
36
36
  return if not_dataset?
37
37
 
38
- klass = Labimotion::DatasetKlass.find_by(id: args[:dataset_klass_id])
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, args[:current_user], args[:element])
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: args[:dataset_klass_id], properties: props, klass_uuid: klass.uuid)
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: args[:dataset_klass_id], element_type: self.class.name, element_id: id, properties: props, klass_uuid: klass.uuid)
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,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,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'labimotion/models/concerns/klass_revision'
4
+ require 'labimotion/models/concerns/metadata_validation'
4
5
 
5
6
  module Labimotion
6
7
  class DatasetKlassesRevision < ApplicationRecord
7
8
  self.table_name = :dataset_klasses_revisions
8
9
  acts_as_paranoid
9
10
  include KlassRevision
11
+ include MetadataValidation
10
12
  belongs_to :dataset_klass, class_name: 'Labimotion::DatasetKlass'
11
13
  end
12
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'
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'labimotion/models/concerns/workflow'
4
4
  require 'labimotion/models/concerns/klass_revision'
5
+ require 'labimotion/models/concerns/metadata_validation'
5
6
 
6
7
  module Labimotion
7
8
  class ElementKlassesRevision < ApplicationRecord
@@ -9,6 +10,7 @@ module Labimotion
9
10
  self.table_name = :element_klasses_revisions
10
11
  include Workflow
11
12
  include KlassRevision
13
+ include MetadataValidation
12
14
  belongs_to :element_klass, class_name: 'Labimotion::ElementKlass'
13
15
 
14
16
  def migrate_workflow
@@ -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,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'labimotion/models/concerns/klass_revision'
4
+ require 'labimotion/models/concerns/metadata_validation'
4
5
 
5
6
  module Labimotion
6
7
  class SegmentKlassesRevision < ApplicationRecord
7
8
  acts_as_paranoid
8
9
  self.table_name = :segment_klasses_revisions
9
10
  include KlassRevision
11
+ include MetadataValidation
10
12
  belongs_to :segment_klass, class_name: 'Labimotion::SegmentKlass'
11
13
  end
12
14
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  ## Labimotion Version
4
4
  module Labimotion
5
- VERSION = '2.1.0.rc14'
5
+ VERSION = '2.2.0.rc1'
6
6
  end
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.rc14
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-04 00:00:00.000000000 Z
12
+ date: 2025-12-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: caxlsx
@@ -122,6 +122,7 @@ files:
122
122
  - lib/labimotion/models/concerns/generic_revisions.rb
123
123
  - lib/labimotion/models/concerns/klass_revision.rb
124
124
  - lib/labimotion/models/concerns/linked_properties.rb
125
+ - lib/labimotion/models/concerns/metadata_validation.rb
125
126
  - lib/labimotion/models/concerns/segmentable.rb
126
127
  - lib/labimotion/models/concerns/workflow.rb
127
128
  - lib/labimotion/models/dataset.rb