labimotion 2.4.0.rc1 → 2.4.0.rc2
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/CHANGELOG.md +21 -0
- data/lib/labimotion/apis/element_variation_api.rb +58 -3
- data/lib/labimotion/apis/generic_klass_api.rb +25 -3
- data/lib/labimotion/apis/labimotion_api.rb +1 -0
- data/lib/labimotion/apis/user_klass_settings_api.rb +70 -0
- data/lib/labimotion/entities/generic_klass_entity.rb +1 -0
- data/lib/labimotion/entities/segment_entity.rb +8 -0
- data/lib/labimotion/entities/user_klass_setting_entity.rb +10 -0
- data/lib/labimotion/helpers/generic_helpers.rb +9 -0
- data/lib/labimotion/helpers/param_helpers.rb +14 -0
- data/lib/labimotion/libs/element_variation_column_set.rb +426 -0
- data/lib/labimotion/libs/element_variation_header.rb +119 -0
- data/lib/labimotion/libs/export_element_variations.rb +245 -0
- data/lib/labimotion/libs/import_element_variations.rb +411 -0
- data/lib/labimotion/libs/linked_element.rb +10 -3
- data/lib/labimotion/libs/sample_association.rb +5 -0
- data/lib/labimotion/models/cellline.rb +47 -0
- data/lib/labimotion/models/concerns/element_fetchable.rb +3 -2
- data/lib/labimotion/models/concerns/segmentable.rb +2 -0
- data/lib/labimotion/models/element.rb +3 -2
- data/lib/labimotion/models/user_klass_setting.rb +12 -0
- data/lib/labimotion/version.rb +1 -1
- data/lib/labimotion.rb +8 -0
- metadata +24 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4c92bee7516a80229220d269bcc9b53d700df17b0fa78f98857476f1bdd9ab02
|
|
4
|
+
data.tar.gz: 70ebf34d13b72d35eaeb4a05e039977add30227afe2acef0c00f1d434f2ae110
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 15952d33d6cceadfc8a3bb21e020e0d924b27e127e84b4fa5667e98bb34a691969d19b642d8624f233ab9c9f18adb2c36d45920594f73fc56296d2a0590c72f5
|
|
7
|
+
data.tar.gz: 2d47c8be30f7ecbbe68db65e8a6979ed7e0d8a1edff6fdaa6fe0dcf1cafbaf1e914f085fdde09385b6546f4be1ba8e0de0830a94584d9aee75d45738ba5f384a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# LabIMotion Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
* Features and enhancements:
|
|
5
|
+
* Added per-user, per-klass toolbar configuration (Overview/Arrange visibility) via `POST /user_klass_settings/save` (upsert) and `GET /user_klass_settings/fetch` ([chem-generic-ui#905](https://github.com/LabIMotion/chem-generic-ui/issues/905)). Each user stores their own `settings` (`{ toolbar: { overview, arrange } }`) per element/segment/dataset klass, keyed by the stable klass identifier so it applies to every instance of that klass across template versions. Requires host ELN twin migration `create_user_klass_settings`.
|
|
6
|
+
* Designer can enable/disable common layer functionalities (record time, add reaction, add/remove layer) per template; template-scoped and independent of template versions ([chem-generic-ui#904](https://github.com/LabIMotion/chem-generic-ui/issues/904)). Saved segments expose the effective klass `settings` so records honor the toggles after a reload. Requires host ELN twin migration `add_settings_to_klasses`.
|
|
7
|
+
* Support linking CellLine elements in the generic Link Element via the `Labimotion::CellLine` wrapper ([chem-generic-ui#906](https://github.com/LabIMotion/chem-generic-ui/issues/906)). Requires a host ELN `element_klasses` row for `cell_line` (migration) — see PR notes.
|
|
8
|
+
* `LinkedElement` resolves `cell_line` links to curated `CelllineSample` columns (previously an unknown el_klass misresolved to a generic `Labimotion::Element` sharing the same id).
|
|
9
|
+
* `LinkedElement` exposes two distinct names for `cell_line` links — the shared **Cell line name** (`material_name`, from the linked `CelllineMaterial`) and the per-sample **Name of specific sample** (`name`) — as separately selectable inline attributes.
|
|
10
|
+
* Element variations can be exported to and imported from Excel (`.xlsx`). The exported workbook is itself the import template: `GET /api/v1/element_variations/:element_id/export` and `POST /api/v1/element_variations/:element_id/import`.
|
|
11
|
+
* The exported sheet carries the grid's grouped header -- group, sub-group and field rows, merged as the grid draws them -- above the hidden key and unit rows. Workbooks from the earlier single-row header still import.
|
|
12
|
+
* Import merges rows by uuid, so a sheet only updates the columns it carries; a row with a blank `Row ID` is added as a new variation.
|
|
13
|
+
* `number`, `integer` and `system-defined` columns accept numbers only. A cell holding anything else is cleared with a warning rather than stored as text, which also cleans up text those columns already hold.
|
|
14
|
+
* Import warnings name the cell they came from (`Cell I6: ...`), so the user can go straight to it in the spreadsheet.
|
|
15
|
+
* Bug fixes:
|
|
16
|
+
* `ElementFetchable#fetch_for_user`: the shared-records branch joined `collection_shares` directly on the element model (an association that only exists on `Collection`), raising `ActiveRecord::ConfigurationError` — rescued into empty search results for every element type. Now joins through `collections`.
|
|
17
|
+
* `Labimotion::Element.fetch_for_user` carried the same broken `collection_shares` join, so the generic-element `search_by_like` endpoint silently returned no shared records. Now joins through `collections` as well.
|
|
18
|
+
* `Labimotion::CellLine` delegation forwards keyword arguments on Ruby >= 3.0 (`ruby2_keywords`); without it `fetch_for_user(id, name:, short_label:, limit:)` raised `ArgumentError`.
|
|
19
|
+
* `SampleAssociation#update_sample_association` no longer creates `Labimotion::ElementsElement` join rows for drag_element values that link standard elements (e.g. `cell_line`, `reaction`), whose `el_id` is not a `Labimotion::Element` id.
|
|
20
|
+
* `Segmentable#save_segments` → `touch_analyses_properties` assumed every segmentable model defines `#analyses`; `CelllineSample` did not, so `POST /api/v1/cell_lines` raised `NameError` on create/update. Guard the analysis-vocabulary touch when `#analyses` is undefined so the save no longer fails.
|
|
21
|
+
* Dependencies:
|
|
22
|
+
* Added `roo` (~> 2.10) for reading the uploaded workbook.
|
|
23
|
+
|
|
3
24
|
## [2.0.0]
|
|
4
25
|
> 2025-03-25
|
|
5
26
|
* Features and enhancements:
|
|
@@ -1,15 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
3
5
|
module Labimotion
|
|
4
6
|
class ElementVariationAPI < Grape::API
|
|
7
|
+
XLSX_CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
8
|
+
|
|
5
9
|
rescue_from ActiveRecord::RecordNotFound do
|
|
6
10
|
error!('404 Element not found', 404)
|
|
7
11
|
end
|
|
8
12
|
|
|
13
|
+
helpers do
|
|
14
|
+
def configure_xlsx_response(filename)
|
|
15
|
+
env['api.format'] = :binary
|
|
16
|
+
content_type XLSX_CONTENT_TYPE
|
|
17
|
+
encoded = URI.encode_www_form_component(filename)
|
|
18
|
+
header('Content-Disposition', "attachment; filename=\"#{filename}\"; filename*=UTF-8''#{encoded}")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def uploaded_xlsx_path!(file)
|
|
22
|
+
filename = file[:filename].to_s
|
|
23
|
+
error!('400 Bad Request - expected an .xlsx file', 400) unless filename.downcase.end_with?('.xlsx')
|
|
24
|
+
|
|
25
|
+
tempfile = file[:tempfile]
|
|
26
|
+
error!('400 Bad Request - upload is empty', 400) if tempfile.nil?
|
|
27
|
+
|
|
28
|
+
tempfile.path
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
9
32
|
resource :element_variations do
|
|
10
33
|
params do
|
|
11
34
|
requires :element_id, type: Integer, desc: 'Generic element id'
|
|
12
35
|
end
|
|
36
|
+
# rubocop:disable Metrics/BlockLength
|
|
13
37
|
route_param :element_id do
|
|
14
38
|
before do
|
|
15
39
|
@element = Labimotion::Element.find(params[:element_id])
|
|
@@ -32,14 +56,45 @@ module Labimotion
|
|
|
32
56
|
|
|
33
57
|
record = Labimotion::ElementVariation.find_or_initialize_by(element_id: @element.id)
|
|
34
58
|
record.variations = params[:variations] || {}
|
|
35
|
-
if params.key?(:layout) && record.class.column_names.include?('layout')
|
|
36
|
-
record.layout = params[:layout] || {}
|
|
37
|
-
end
|
|
59
|
+
record.layout = params[:layout] || {} if params.key?(:layout) && record.class.column_names.include?('layout')
|
|
38
60
|
record.save!
|
|
39
61
|
|
|
40
62
|
present record, with: Labimotion::ElementVariationEntity, root: 'element_variation'
|
|
41
63
|
end
|
|
64
|
+
|
|
65
|
+
desc 'Export element variations as an xlsx workbook'
|
|
66
|
+
get :export do
|
|
67
|
+
exporter = Labimotion::ExportElementVariations.new(@element, user: current_user)
|
|
68
|
+
configure_xlsx_response(exporter.filename)
|
|
69
|
+
exporter.read
|
|
70
|
+
rescue StandardError => e
|
|
71
|
+
Labimotion.log_exception(e, current_user)
|
|
72
|
+
error!("500 Internal Server Error: #{e.message}", 500)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
desc 'Import element variations from an xlsx workbook produced by the export'
|
|
76
|
+
params do
|
|
77
|
+
requires :file, type: File, desc: 'xlsx file'
|
|
78
|
+
end
|
|
79
|
+
post :import do
|
|
80
|
+
error!('401 Unauthorized', 401) unless ElementPolicy.new(current_user, @element).update?
|
|
81
|
+
|
|
82
|
+
path = uploaded_xlsx_path!(params[:file])
|
|
83
|
+
importer = Labimotion::ImportElementVariations.new(@element, path)
|
|
84
|
+
record = importer.execute!
|
|
85
|
+
|
|
86
|
+
{
|
|
87
|
+
element_variation: Labimotion::ElementVariationEntity.represent(record),
|
|
88
|
+
warnings: importer.warnings
|
|
89
|
+
}
|
|
90
|
+
rescue Labimotion::ImportElementVariations::InvalidWorkbook => e
|
|
91
|
+
error!(e.message, 422)
|
|
92
|
+
rescue StandardError => e
|
|
93
|
+
Labimotion.log_exception(e, current_user)
|
|
94
|
+
error!("500 Internal Server Error: #{e.message}", 500)
|
|
95
|
+
end
|
|
42
96
|
end
|
|
97
|
+
# rubocop:enable Metrics/BlockLength
|
|
43
98
|
end
|
|
44
99
|
end
|
|
45
100
|
end
|
|
@@ -14,7 +14,7 @@ module Labimotion
|
|
|
14
14
|
desc 'export klass'
|
|
15
15
|
params do
|
|
16
16
|
requires :id, type: Integer, desc: 'element id'
|
|
17
|
-
requires :klass, type: String, desc: 'Klass', values:
|
|
17
|
+
requires :klass, type: String, desc: 'Klass', values: Labimotion::Constants::Klass::ALL
|
|
18
18
|
end
|
|
19
19
|
get do
|
|
20
20
|
entity = "Labimotion::#{params[:klass]}".constantize.find_by(id: params[:id])
|
|
@@ -35,7 +35,7 @@ module Labimotion
|
|
|
35
35
|
namespace :de_activate do
|
|
36
36
|
desc 'activate or deactivate Generic Klass'
|
|
37
37
|
params do
|
|
38
|
-
requires :klass, type: String, desc: 'Klass', values:
|
|
38
|
+
requires :klass, type: String, desc: 'Klass', values: Labimotion::Constants::Klass::ALL
|
|
39
39
|
requires :id, type: Integer, desc: 'Klass ID'
|
|
40
40
|
requires :is_active, type: Boolean, desc: 'Active or Inactive Klass'
|
|
41
41
|
end
|
|
@@ -54,11 +54,33 @@ module Labimotion
|
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
namespace :update_settings do
|
|
58
|
+
desc 'update Generic Klass settings'
|
|
59
|
+
params do
|
|
60
|
+
requires :klass, type: String, desc: 'Klass', values: Labimotion::Constants::Klass::ALL
|
|
61
|
+
requires :id, type: Integer, desc: 'Klass ID'
|
|
62
|
+
requires :settings, type: Hash, desc: 'Klass settings'
|
|
63
|
+
end
|
|
64
|
+
after_validation do
|
|
65
|
+
authenticate_admin!(params[:klass].gsub(/(Klass)/, 's').downcase)
|
|
66
|
+
fetch_klass(params[:klass], params[:id])
|
|
67
|
+
end
|
|
68
|
+
post do
|
|
69
|
+
updated_klass = update_klass_settings(params)
|
|
70
|
+
entity_class = "Labimotion::#{params[:klass]}Entity".constantize
|
|
71
|
+
serialized_data = entity_class.represent(updated_klass)
|
|
72
|
+
{ mc: 'ss00', data: serialized_data }
|
|
73
|
+
rescue StandardError => e
|
|
74
|
+
Labimotion.log_exception(e, current_user)
|
|
75
|
+
{ mc: 'se00', msg: e.message, data: {} }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
57
79
|
namespace :fetch do
|
|
58
80
|
desc 'fetch Generic Klass by id'
|
|
59
81
|
params do
|
|
60
82
|
requires :id, type: Integer, desc: 'Klass ID'
|
|
61
|
-
requires :klass, type: String, desc: 'Klass', values:
|
|
83
|
+
requires :klass, type: String, desc: 'Klass', values: Labimotion::Constants::Klass::ALL
|
|
62
84
|
end
|
|
63
85
|
get do
|
|
64
86
|
klass_obj = fetch_klass(params[:klass], params[:id])
|
|
@@ -13,6 +13,7 @@ module Labimotion
|
|
|
13
13
|
mount Labimotion::StandardLayerAPI
|
|
14
14
|
mount Labimotion::VocabularyAPI
|
|
15
15
|
mount Labimotion::UserAPI
|
|
16
|
+
mount Labimotion::UserKlassSettingsAPI
|
|
16
17
|
mount Labimotion::MttAPI
|
|
17
18
|
mount Labimotion::ElementVariationAPI
|
|
18
19
|
mount Labimotion::LabimotionDoiAPI
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'labimotion/version'
|
|
4
|
+
|
|
5
|
+
module Labimotion
|
|
6
|
+
# Per-user, per-klass UI settings API (toolbar Overview/Arrange visibility).
|
|
7
|
+
# Every route is scoped to the authenticated user via created_by, so a user
|
|
8
|
+
# only ever reads/writes their own setting; no klass-edit permission needed.
|
|
9
|
+
class UserKlassSettingsAPI < Grape::API
|
|
10
|
+
helpers Labimotion::ParamHelpers
|
|
11
|
+
|
|
12
|
+
helpers do
|
|
13
|
+
def settings_scope
|
|
14
|
+
Labimotion::UserKlassSetting.where(created_by: current_user.id)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def klass_toolbar(settings)
|
|
18
|
+
(settings || {})['toolbar'] || (settings || {})[:toolbar] || {}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
resource :user_klass_settings do
|
|
23
|
+
desc 'Fetch the current user UI setting for a klass'
|
|
24
|
+
params do
|
|
25
|
+
requires :klass, type: String, values: %w[ElementKlass SegmentKlass DatasetKlass], desc: 'Klass type'
|
|
26
|
+
requires :identifier, type: String, desc: 'Klass identifier'
|
|
27
|
+
end
|
|
28
|
+
get 'fetch' do
|
|
29
|
+
error!('401 Unauthorized', 401) unless current_user
|
|
30
|
+
|
|
31
|
+
record = settings_scope.find_by(klass: params[:klass], klass_identifier: params[:identifier])
|
|
32
|
+
data = record ? Labimotion::UserKlassSettingEntity.represent(record) : nil
|
|
33
|
+
{ mc: 'ss00', data: data }
|
|
34
|
+
rescue StandardError => e
|
|
35
|
+
Labimotion.log_exception(e, current_user)
|
|
36
|
+
{ mc: 'se00', msg: e.message, data: nil }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
desc 'Upsert the current user UI setting for a klass'
|
|
40
|
+
params do
|
|
41
|
+
use :user_klass_settings_save
|
|
42
|
+
end
|
|
43
|
+
post 'save' do
|
|
44
|
+
error!('401 Unauthorized', 401) unless current_user
|
|
45
|
+
|
|
46
|
+
record = settings_scope.find_or_initialize_by(
|
|
47
|
+
klass: params[:klass], klass_identifier: params[:klass_identifier]
|
|
48
|
+
)
|
|
49
|
+
record.klass_label = params[:klass_label] if params[:klass_label]
|
|
50
|
+
record.created_by ||= current_user.id
|
|
51
|
+
record.settings = (record.settings || {}).merge('toolbar' => klass_toolbar(params[:settings]))
|
|
52
|
+
record.save!
|
|
53
|
+
{ mc: 'ss00', data: Labimotion::UserKlassSettingEntity.represent(record) }
|
|
54
|
+
rescue StandardError => e
|
|
55
|
+
Labimotion.log_exception(e, current_user)
|
|
56
|
+
{ mc: 'se00', msg: e.message, data: {} }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
desc 'List all UI settings of the current user'
|
|
60
|
+
get 'list' do
|
|
61
|
+
error!('401 Unauthorized', 401) unless current_user
|
|
62
|
+
|
|
63
|
+
{ mc: 'ss00', data: Labimotion::UserKlassSettingEntity.represent(settings_scope.to_a) }
|
|
64
|
+
rescue StandardError => e
|
|
65
|
+
Labimotion.log_exception(e, current_user)
|
|
66
|
+
{ mc: 'se00', msg: e.message, data: [] }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -9,6 +9,7 @@ module Labimotion
|
|
|
9
9
|
expose :properties_template, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
10
10
|
expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
11
11
|
expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
12
|
+
expose :settings, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
12
13
|
expose_timestamps(timestamp_fields: %i[released_at created_at updated_at sync_time])
|
|
13
14
|
end
|
|
14
15
|
end
|
|
@@ -9,9 +9,17 @@ module Labimotion
|
|
|
9
9
|
expose :properties, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
10
10
|
expose :properties_release, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
11
11
|
expose :metadata, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
12
|
+
expose :settings, **DISPLAYED_IN_LIST_CONDITION, anonymize_with: {}
|
|
12
13
|
|
|
13
14
|
def klass_label
|
|
14
15
|
object.segment_klass.label
|
|
15
16
|
end
|
|
17
|
+
|
|
18
|
+
# Saved segments are serialized without their klass, so surface the
|
|
19
|
+
# template-scoped settings here; guarded for hosts not yet migrated.
|
|
20
|
+
def settings
|
|
21
|
+
klass = object.segment_klass
|
|
22
|
+
klass.respond_to?(:settings) ? klass.settings || {} : {}
|
|
23
|
+
end
|
|
16
24
|
end
|
|
17
25
|
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'labimotion/entities/application_entity'
|
|
4
|
+
module Labimotion
|
|
5
|
+
# Per-user, per-klass UI setting entity
|
|
6
|
+
class UserKlassSettingEntity < Labimotion::ApplicationEntity
|
|
7
|
+
expose :id, :klass, :klass_identifier, :klass_label, :settings
|
|
8
|
+
expose_timestamps(timestamp_fields: %i[created_at])
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -36,6 +36,15 @@ module Labimotion
|
|
|
36
36
|
raise e
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
def update_klass_settings(params)
|
|
40
|
+
klz = fetch_klass(params[:klass], params[:id])
|
|
41
|
+
klz&.update!(settings: (klz.settings || {}).merge(params[:settings] || {}))
|
|
42
|
+
klz
|
|
43
|
+
rescue StandardError => e
|
|
44
|
+
Labimotion.log_exception(e, current_user)
|
|
45
|
+
raise e
|
|
46
|
+
end
|
|
47
|
+
|
|
39
48
|
def delete_klass(params)
|
|
40
49
|
authenticate_admin!(params[:klass].gsub(/(Klass)/, 's').downcase)
|
|
41
50
|
klz = fetch_klass(params[:klass], params[:id])
|
|
@@ -14,6 +14,7 @@ module Labimotion
|
|
|
14
14
|
optional :klass_prefix, type: String, desc: 'Klass klass_prefix'
|
|
15
15
|
optional :icon_name, type: String, desc: 'Klass icon_name'
|
|
16
16
|
optional :metadata, type: Hash, desc: 'Klass metadata'
|
|
17
|
+
optional :settings, type: Hash, desc: 'Klass settings'
|
|
17
18
|
requires :properties_template, type: Hash, desc: 'Klass template'
|
|
18
19
|
optional :properties_release, type: Hash, desc: 'Klass release'
|
|
19
20
|
optional :released_at, type: DateTime, desc: 'Klass released_at'
|
|
@@ -72,6 +73,7 @@ module Labimotion
|
|
|
72
73
|
requires :label, type: String, desc: 'Klass label'
|
|
73
74
|
optional :desc, type: String, desc: 'Klass desc'
|
|
74
75
|
optional :metadata, type: Hash, desc: 'Klass metadata'
|
|
76
|
+
optional :settings, type: Hash, desc: 'Klass settings'
|
|
75
77
|
requires :properties_template, type: Hash, desc: 'Klass template'
|
|
76
78
|
optional :properties_release, type: Hash, desc: 'Klass release'
|
|
77
79
|
optional :released_at, type: DateTime, desc: 'Klass released_at'
|
|
@@ -153,5 +155,17 @@ module Labimotion
|
|
|
153
155
|
requires :id, type: Integer, desc: 'Element ID'
|
|
154
156
|
requires :wellplate_ids, type: Array, desc: 'Selected Wellplates'
|
|
155
157
|
end
|
|
158
|
+
|
|
159
|
+
params :user_klass_settings_save do
|
|
160
|
+
requires :klass, type: String, values: %w[ElementKlass SegmentKlass DatasetKlass], desc: 'Klass type'
|
|
161
|
+
requires :klass_identifier, type: String, desc: 'Stable klass identifier'
|
|
162
|
+
optional :klass_label, type: String, desc: 'Klass label (display only)'
|
|
163
|
+
requires :settings, type: Hash do
|
|
164
|
+
optional :toolbar, type: Hash do
|
|
165
|
+
optional :overview, type: Boolean, default: true
|
|
166
|
+
optional :arrange, type: Boolean, default: true
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
156
170
|
end
|
|
157
171
|
end
|